1

Вопрос по c – как избежать изменения значения 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, ...

Просто никогда не игнорируйте предупреждение. Язык C только указывает, что «диагностика» должен быть выдан. Предупреждения так же серьезны, как и ошибки.

от Jens Gustedt

Какой компилятор вы используете?

от Fred Foo

GCC v4.5.2 на Linux дает мне вывод<code>*p = 20 i = 20</code>Странно, что ваш вывод отличается.

от majie

@JensGustedt: некоторые предупреждения<i>not</i> Требуется языком, хотя, и просто раздражение (например, & quot;<i>Suggest parantheses around assignment used as truth value</i>& Quot;).

от caf

@majie: попробуйте с оптимизацией.

от caf

4 ответа

0

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

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

#include <stdio.h>
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;
}
1

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

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

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

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

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

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

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

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

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

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

2

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

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

7

Прежде всего, компилятор выдаст предупреждение из-за кода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 заглянуть в код сборки.

Похожие вопросы