Const变量在C中用指针改变

时间:2012-02-21 03:46:13

标签: c++ c pointers const

变量i被声明为const,但我仍然可以使用指向它的内存位置的指针来更改该值。怎么可能?

int main()
{

    const int i = 11;
    int *ip = &i;
    *ip=100;
    printf("%d\n",*ip);
    printf("%d\n",i);
}

编译时,我收到此警告:

test.c: In function ‘main’:
test.c:11: warning: initialization discards qualifiers from pointer target type

输出就是这个

100
100

5 个答案:

答案 0 :(得分:8)

const编译时功能 它不会阻止你在脚下射击自己;这就是警告的目的。

答案 1 :(得分:8)

const不是对编译器的请求,使其无法更改该变量。相反,它是编译器的 promise ,你不会。如果你违背诺言,你的程序可以做任何事情,包括崩溃。

例如,如果我使用具有-O2优化级别的gcc编译示例代码,则输出为:

100
11

编译器允许const限定变量放在只读内存中,但它 <(除了其他任何内容,某些环境不实现任何此类事情)。特别是,将自动(“本地”)变量放在只读存储器中几乎总是不切实际的。

如果您将i的声明更改为:

static const int i = 11;

然后你可能会发现程序现在在运行时崩溃了。

答案 2 :(得分:3)

虽然它可能是C中的警告,但这是C ++中的编译器错误。

如果你以某种方式设法在C / C ++中强制转换const int,那么它可能会导致未定义的行为。原因是,您将const int i =中的数字(即; 11 const)转换为可变值。

您的代码显示的内容与以下序列之间存在差异:

int x = 11;    // x is modifiable
const int i = x;
int *ip = (int*)(&i);  // ok
*ip=100;

答案 3 :(得分:2)

无法修改const - 限定对象。如果进行了这样的尝试,程序将表现出未定义的行为(C99 6.7.3.5)。 (您的程序不正确。)

有关const的更多内容: 声明为const 的对象可以进行修改,但不能使用{{1合格的左值。当涉及指针时,这是最明显的。例如,考虑声明:

const

可以通过int i = 10; int *p1 = &i; const int *p2 = &i; 本身和i修改i,但不能通过p1修改p2。这意味着*p2可以评估为不同的值,即使p2指向const对象,因为其他语句可能会更改{{{ 1}}(别名指针,如示例中所示)。

但是,如果p2本身是i - 合格,那么尝试通过const修改它将产生未定义的行为(正如您的代码所做的那样)。

答案 4 :(得分:0)

不是尝试修改导致程序行为未定义的i,而是ip的初始化。

const int i = 11;
int *ip = &i;

&i的类型为const int*ip的类型为int*。尝试使用int*值初始化const int*约束违规。符合要求的实施需要发布诊断;一旦完成,它可能会也可能不会拒绝翻译单位。如果它接受它,C标准就没有说明最终程序的行为。

接受此类操作的编译器通常生成的代码相当于从const int*int*的转换,使声明有效地等同于:

int *ip = (int*)&i;

但该语言不需要此行为。

请勿忽略警告。

(注意,使用强制转换,代码不违反约束;然后是以下行为

*ip = 100;

未定义,因为它尝试修改const - 限定对象。)

特别是gcc在很多情况下会将约束违规的诊断处理(默认情况下)作为警告而不是致命错误。我个人不喜欢gcc;它允许通过太多糟糕的代码。

(您的计划行为也未定义,因为您在没有明显声明的情况下致电printf;添加#include <stdio.h>int main()应为int main(void)。)