Intereting Posts
Макрооценка в препроцессоре c Почему этот адрес памяти% fs: 0x28 (fs ) имеет случайное значение? Существуют ли какие-либо «шаблоны проектирования» в C? Выполнять только препроцессор, но только для определенных операторов Программирование сокетов Разрешение отклонено Что происходит, когда макрос препроцессора C определяется дважды? Труба нескольких файлов (gz) в программу C Какой из этих двухмерных массивов выгодно использовать и почему? Предупреждение C (gcc): инициализация из несовместимого типа указателя при вызове pthread_cleanup_push () сокращенный указатель typedef на константу struct Как читать ansible вход без блокировки в Windows инициализация узла связанной структуры Когда передать указатель на структуру в качестве аргумента и когда передать указатель на указатель на структуру? В C, как определить макрос, используя другие macros, когда эти другие macros вызывают конфликты имен количество аргументов для функции в pthread

как избежать изменения значения const в C

Привет, я новичок в мире программирования, я хочу знать, как избежать изменения значения константной переменной.

#include  int main() { const int i = 10; int * p = &i; *p = 20; printf("*p = %d\ni = %d\n", *p,i); printf("%u\n%u\n",&i, p); return 0; } 

здесь, в вышеприведенной программе, я получаю только предупреждение, но не ошибка, пока я назначаю значение в поле const с помощью указателя, но когда я печатаю, это не так:

 *p = 20 i = 10 3210723532 3210723532 

так что тогда использование получения указателя на const, когда оно не изменяется.

В стандарте C используется только термин «диагностика». Существует никаких различий между предупреждениями и ошибками.

Преобразование const int * в int * без приведения является нарушением ограничения, которое требует диагностики.

Это ставит его в ту же категорию, что и синтаксическая ошибка: ваш код не является допустимой программой ISO C, и поведение не определено, если оно все равно переведено и выполнено.

К сожалению, многие компиляторы не различают требуемую диагностику от дополнительной диагностики, которую они добавляют, а что хуже, иногда они требуют диагностики в качестве предупреждений. Это разрешено: стандарт C не говорит о том, что программы, требующие диагностики, должны быть исключены из перевода и выполнения. Выпуская предупреждение, компилятор удовлетворяет требованиям для диагностики, и это все.

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

Компилятор GNU C понимает диалект C, называемый GNU C 89, если вы не даете ему никаких диалектов.

Таким образом, по иронии судьбы, на этом диалекте это просто предупреждение для преобразования const int * в int * без приведения в действие, тогда как некоторые законные программы C90 полностью отвергаются.

Поэтому в основном вы всегда должны понимать, как управлять входным диалектом вашего компилятора, и следить за всеми предупреждениями, которые вы должны сами понять, являются ли они реальными нарушениями языка или просто капризами компилятора писателей («предлагать круглые скобки вокруг этого выражения»).

gcc -Wall -W -ansi идея компиляции с gcc -Wall -W -ansi (если вы программируете на C90 или -std=c99 вместо ansi для C99) и убедитесь, что нет предупреждений. Даже стилистические, которые предлагают дополнительные круглые скобки и тому подобное. Если вы недостаточно дисциплинированы, чтобы следить за предупреждениями, добавьте -Werror чтобы превратить их в ошибки, которые не позволяют построить. Некоторые также рекомендовали бы- -pedantic .

Если вы будете следовать этой дисциплине, подрывная const int не будет проникать в вашу кодовую базу.

Прежде всего, компилятор выдаст предупреждение из-за кода int * p = &i;

и значение i не изменяется, потому что компиляция оптимизирует код, я использую gcc для проверки кода:

если я использую gcc -O0 const.c -o const , O0 представляет собой оптимизацию компилятора, результат

 *p = 20 i = 20 1114013412 1114013412 

но когда я использую gcc -O2 const.c -o const , O2 представляет оптимизацию компилятора, результат

 *p = 20 i = 10 1262279764 1262279764 

Таким образом, компилятор знает, что тип i является const и заменяет i на 10 во время компиляции, и, следовательно, код становится

  printf("*p = %d\ni = %d\n", *p,10); 

Также вы можете использовать gcc -S const.c для просмотра кода сборки.

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

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

Сделайте вместо него #define .

Объекты, объявленные const , не являются постоянными в английском значении термина, они «доступны только для чтения».

 #include  int main() { #define I 10 int * p = &I; // illegal &I *p = 20; printf("*p = %d\nI = %d\n", *p,I); printf("%u\n%u\n",&I, p); // illegal &I return 0; }