如何避免在C中改变const的值

嗨,我是编程世界的初学者,我想知道如何避免改变const变量的值。

#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 *转换的情况下将const int *转换为const int *是一种需要诊断的约束违规。

这使它与语法错误属于同一类别:您的代码不是有效的ISO C程序,如果它仍然被翻译并执行,则行为是未定义的。

遗憾的是,许多编译器没有区分所需的诊断和它们添加的额外诊断,更糟糕的是,它们有时需要诊断作为警告。 这是允许的:C标准并未说明必须防止需要诊断的程序进行翻译和执行。 通过发出警告,编译器满足诊断要求即可。

另一个问题是许多C编译器甚至不接受标准ISO C方言,除非他们被要求,而是接受他们自己的方言,这可能具有不一致(即不向后兼容)的扩展。

GNU C编译器理解一个名为GNU C 89的C语言,如果你不给它任何方言选项。

所以,具有讽刺意味的是,在这种方言中,仅仅警告将const int *转换为int *而不进行强制转换,而某些合法的C90程序则被完全拒绝。

所以基本上你总是要了解如何控制编译器的输入方言,并自己跟踪所有警告,你必须自己理解,是否真的违反了语言,或只是编译器的想法作家(“建议围绕这个表达的括号”)。

使用gcc -Wall -W -ansi进行编译并不是一个坏主意(如果你在C90编程;或者-std=c99而不是ansi用于C99)并确保没有警告。 甚至没有那些暗示额外括号等的风格。 如果您没有足够的纪律来跟进警告,请添加-Werror将其转换为构建失败的错误。 有些人还会推荐-pedantic

如果你遵循这个规则, const int的subversion将不会潜入你的代码库。

首先,由于代码int * p = &i; ,编译器将发出警告int * p = &i;

并且i的值没有改变,因为编译优化代码,我使用gcc来测试代码:

如果我使用gcc -O0 const.c -o constO0表示没有编译器优化,结果是

 *p = 20 i = 20 1114013412 1114013412 

但是当我使用gcc -O2 const.c -o constO2表示编译器优化,结果是

 *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; }