как ключевое слово константы работает в c

Я хочу знать о внутренностях константы в c и C++. Как компилятор налагает постоянность? Может кто-то помогать мне.

9
задан Skurmedel 11 May 2010 в 17:16
поделиться

6 ответов

В общем, const - это 100% компилятор. Когда вы объявляете что-то const, компилятор накладывает ограничения на то, что он позволяет вам писать. Он не позволит вам назначить константный скаляр, назначить через ссылку на константу или указатель или или вызвать неконстантную функцию объекта const.

Нет никакой гарантии, что компилятор организует какую-либо защиту во время выполнения.

21
ответ дан 4 December 2019 в 06:22
поделиться

Ключевое слово const в C и C ++ имеет два разных семантических значения.

(1) Он может объявлять постоянство объекта

const SomeType t;

В приведенном выше случае объект t является немодифицируемым объектом. Компилятор сделает все возможное, чтобы вы не изменили его, соблюдая правила const-correness (которые не совпадают в C и C ++). Правила константной корректности применяются только концептуально, на уровне языка, что означает, что есть способы обойти эти правила, а также означает, что константность объекта не обязательно будет реализована на физическом уровне. Т.е. нет никакой гарантии, что объект в конечном итоге будет помещен в постоянную память.

Важно отметить, что этот вид константности не может быть устранен в том смысле, что любые попытки изменить вышеуказанный объект путем отказа от константности приводят к неопределенному поведению (за исключением возможного изменяемого членов в C ++).

(2) Он может объявлять постоянство пути доступа к объекту

const SomeType *p;

Вышеупомянутый p объявлен как указатель на константу.Это не обязательно означает, что объект p , на который указывает, является постоянным объектом (как определено выше первым видом const ). Он легко может быть непостоянным, и в этом случае совершенно законно отбросить константу из указанного выше пути доступа и изменить объект, хотя обычно это не очень хорошая практика программирования. Другими словами, постоянство пути доступа потенциально устранимо .

Принимая во внимание вышеизложенное, следующее объявление

const int* const* const* const p = 0;

включает два разных вида const : самый последний const объявляет постоянство объекта p ] (первый вид), тогда как остальная часть const объявляет постоянство различных уровней пути доступа, представленных p (второй вид).

P.S. В качестве [возможно несвязанного] примечания, вероятно, стоит отметить, что термин константа имеет совершенно разные значения в C и C ++. В C ++ константы - это объекты, объявленные как const . В C константы являются литералами. Объекты, объявленные как const , не являются константами в терминологии C.

10
ответ дан 4 December 2019 в 06:22
поделиться

В дополнение к принудительной неизменяемости во время компиляции, обеспечиваемой с помощью ключевого слова const , которое уже упоминалось в других ответах на ваш вопрос, с использованием иногда он позволяет компилятору помещать такие данные в раздел только для чтения двоичного файла и памяти. Согласно Разделу 2.4.2 «Forever const » в статье Ульриха Дреппера Как писать общие библиотеки , это потенциально позволяет программам (1) использовать меньше ресурсов и (2) быстрее запускаться. .

Обратите внимание, что отказ от константности данных в таких областях памяти, доступных только для чтения, обычно приводит к неопределенному поведению.

4
ответ дан 4 December 2019 в 06:22
поделиться

Когда компилятор компилирует код, он вычисляет тип каждого выражения, чтобы он мог проверить их тип и правильно выдать код (например, предупреждение, когда вы пытаетесь сохранить int в указателе или правильно преобразовывать целое число в двойной). const -ность можно рассматривать как часть типа. Поскольку у него есть информация о типе выражения, он может проверить тип lvalue (левая часть присваивания) и выдать ошибку, если в его типе есть «const».

2
ответ дан 4 December 2019 в 06:22
поделиться

В языке C ключевое слово const делает переменную неизменяемой, то есть ее нельзя изменить.

Обычно это различие делается во время компиляции и не влияет на модификацию переменной во время выполнения. Например, переменная const может быть косвенно изменена с помощью указателя на тот же адрес памяти.

В C++ ключевое слово const имеет более чем одно значение.

Например, функция-член класса может быть "const", что означает, что ей не разрешается изменять состояние экземпляра класса.

Как и в C, переменная, объявленная const, может быть изменена косвенно с помощью указателя, а также с помощью ключевого слова "mutable" или оператора const_cast<>.

1
ответ дан 4 December 2019 в 06:22
поделиться

На самом деле это очень сложная вещь для оптимизирующего компилятора. Однако все начинается просто.

Когда вы объявляете переменную с ключевым словом const (давайте просто проигнорируем указатели, потому что они могут быть константами, указывать на константу или и то, и другое), компилятор запоминает, что никакой код не должен изменять эту переменную (почти). Если компилятор видит код, который изменяет константную переменную, он считает, что это ошибка (или иногда заслуживает предупреждения, но для простоты я проигнорирую это). Компилятор также предполагает, что никакой код, который он не может видеть (в любом случае прямо сейчас {код в других файлах .c или, возможно, библиотеке или .s или.asm-файлы) изменят переменную const (если только она не const volatile , и в этом случае она будет предполагать, что она может измениться в любой момент, но все равно не позволит вашему коду изменить ее - это полезно для SFR с отображением в память [регистры специальных функций], которые используются для чтения состояния устройства, но не могут быть записаны. Помните, что c и c ++ используются для ОС и встроенного программирования).

Предположение, что переменная не изменится при некоторых или всех обстоятельствах, позволяет подпрограммам оптимизации компилятора делать то, что в противном случае было бы невозможно. Это означает такие вещи, как размещение буквального значения переменной в потоке инструкций, а не загрузка адреса переменной, а затем загрузка значения переменной. Он также может предположить, что если он загружен, то if:

extern const int foo; // note that the value isn't visible, so a load is necessary
...
extern int baz(int, int);
...
int bar(int x, int y) {
   int m, n;
   int r = x / foo; // this would require loading the value of foo from RAM
   m = baz(r, y); // the compiler normally has to assume that a function could change a global
   n = m + r + foo; // but since the global foo is const it shouldn't be able to be changed
                    // by the call to baz and does not need to be reloaded
   return n;
}

Исполняемый файл (или другой объектный файл) может иметь раздел (.rodata), в котором есть только константы. Во многих случаях ОС может потребовать запретить программе запись в эти данные (или в некоторых случаях это может быть даже в ПЗУ). Этот раздел может также содержать версии неконстантных переменных, которые используются для инициализации, поскольку в нем может быть любая константа, а не только константы, объявленные как константы.

Таким образом, в C const в основном просто говорит компилятору сказать вам, что вы напортачили и пытаетесь изменить то, что не должно было быть изменено. Тем не менее, на его основе можно делать некоторые предположения.

В C ++ все усложняется.Я не помню всех деталей, но я помню, что вы можете перегрузить имя функции в зависимости от того, является ли значение, которое вы передаете ей, const или нет, что может быть полезно.

1
ответ дан 4 December 2019 в 06:22
поделиться