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

时间:2012-04-10 09:12:32

标签: c

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

#include <stdio.h>
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的指针是什么用途。

4 个答案:

答案 0 :(得分:7)

首先,由于代码int * p = &i;

,编译器将发出警告

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

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

*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查看汇编代码。

答案 1 :(得分:2)

C语言标准(几乎)从不要求编译器拒绝错误的代码。如果你写了一些非法的东西,并且编译器只是警告你,那么就C语言标准而言,编译器已经完成了它的工作。

您需要非常认真地对待编译器警告。如果您的代码在没有警告错误的情况下编译,那么它可能是合法的(这并不意味着它实际上会起作用!)。

答案 2 :(得分:1)

C标准仅使用术语“诊断”。警告和错误之间没有区别。

const int *转换为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的颠覆将不会潜入您的代码库。

答案 3 :(得分: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;
}