Const变量随C中的指针而更改

Const variable changed with pointer in C

本文关键字:指针 变量 Const      更新时间:2023-10-16

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

int main()
{
    const int i = 11;
    int *ip = &i;
    *ip=100;
    printf("%dn",*ip);
    printf("%dn",i);
}

当我编译时,我会收到以下警告:

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

输出是这个

100
100

const不是向编译器发出的使其无法更改该变量的请求。相反,这是对编译器的一个承诺,而您不会这样做。如果你违背了你的承诺,你的程序可以做任何事情,包括崩溃。

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

100
11

编译器允许const限定变量放置在只读内存中,但它没有到(除其他外,有些环境不实现任何此类功能)。特别是,将自动("本地")变量放在只读存储器中几乎总是不切实际的。

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

static const int i = 11;

那么您很可能会发现该程序现在在运行时崩溃。

const编译时功能
这并不能阻止你朝自己的脚开枪;这就是警告的意义所在。

虽然这在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;

不能修改符合const条件的对象。如果进行了这样的尝试,则程序显示出未定义的行为(C99 6.7.3.5)。(您的程序不正确。)

关于const的更多信息:而非声明为const的对象可以修改,但不能使用const限定的lvalues。当涉及指针时,这一点最为明显。例如,考虑声明:

int i = 10;
int *p1 = &i;
const int *p2 = &i;

可以通过i本身和通过p1修改i,但不能通过p2修改。这意味着,即使p2指向const对象,*p2也可以评估为不同的值,因为其他语句可能会更改p2指向的对象(如示例中的混叠指针)。

但是,如果i本身是const限定的,那么尝试通过p1修改它将产生未定义的行为(就像您的代码一样)。

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

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

CCD_ 28属于CCD_。CCD_ 30属于CCD_。试图用const int*值初始化int*是违反约束的行为。发布诊断需要符合要求的实施;一旦完成,它可能会也可能不会拒绝翻译单元。如果它接受它,C标准就不会对生成的程序的行为做任何说明。

接受这些东西的编译器通常会生成等效于从const int*int*的转换的代码,从而使声明实际上等效于:

int *ip = (int*)&i;

但是语言不需要这种行为。

不要忽视警告

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

*ip = 100;

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

特别是gcc在很多情况下,对违反约束的诊断(默认情况下)被处理为警告,而不是致命错误。我个人不喜欢gcc;它让太多坏代码通过。

(您的程序的行为也是未定义的,因为您在没有可见声明的情况下调用printf;添加#include <stdio.h>。并且int main()应该是int main(void)。)