Привет, я новичок в мире программирования, я хочу знать, как избежать изменения значения константной переменной.
#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; }