我们可以通过指针改变用const定义的对象的值吗?

#include  int main() { const int a = 12; int *p; p = &a; *p = 70; } 

它会起作用吗?

它是“未定义的行为”,意味着基于标准,您无法预测尝试此操作时会发生什么。 根据特定的机器,编译器和程序状态,它可能会执行不同的操作。

在这种情况下,最常发生的是答案是“是”。 变量const或非变量只是内存中的一个位置,您可以打破常量规则并简单地覆盖它。 (当然,如果程序的某些其他部分依赖于其const数据是恒定的,这将导致严重的错误!)

但是在某些情况下 – 最常见的是const static数据 – 编译器可能会将这些变量放在只读的内存区域中。 例如,MSVC通常将const static int放在可执行文件的.text段中,这意味着如果您尝试写入操作系统将引发保护错误,程序将崩溃。

在编译器和机器的其他组合中,可能会发生完全不同的事情。 您可以肯定的一点是,这种模式会让任何必须阅读您的代码的人烦恼。

这是未定义的行为。 certificate:

 /* program.c */ int main() { const int a = 12; int* p; p = &a; *p = 70; printf("%d\n", a); return 0; } gcc program.c 

并运行它。 输出为70(gcc 4.3)

然后像这样编译它:

 gcc -O2 program.c 

并运行它。 输出将是12.当它进行优化时,编译器可能会将12加载到寄存器中,并且在需要访问printf时不会再次加载它,因为它“知道”a不能更改。

通过指针修改const限定对象会调用未定义的行为,结果就是这样。 它可能是你期望的东西,即。 如果已放入.text等,则前一个值不变

它确实适用于gcc。 它不喜欢它:

test.c:6:警告:赋值从指针目标类型中丢弃限定符

但是执行时价值确实发生了变化。 我不会指出明显的禁忌……

是的,你可以通过使用这样的代码完成它。 但是当a是全局的时(gcc编译的程序给我segmentation fault ),代码不适用。

一般来说,在心爱的C中,你几乎总能找到一些不应该被改变或暴露的东西。 这里的const就是一个例子。

但考虑到这个可怜的家伙(也许是我自己6个月后)维护我们的代码,我经常选择不这样做。

这里指针p的类型是int* ,它被赋值为const int*的类型( &a => const int变量的地址)。

隐式强制转换消除了常量,但gcc会发出警告(请注意这在很大程度上取决于实现)。

由于指针未声明为const ,因此可以使用此指针更改值。

如果指针被声明为const int* p = &a ,则无法执行*p = 70

您不能通过使用指向它的指针来更改常量变量的值。 这种类型的指针称为Pointer to a constant

还有另一种称为Constant Pointer概念。 这意味着一旦指针指向内存位置,就无法指向另一个位置。

糟糕,不好主意。

此外,行为是特定于平台和实现的。 如果你在一个平台上运行常量存储在不可写内存中,这显然是行不通的。

而且,为什么你想要? 更新源中的常量,或将其设为变量。

此代码包含约束违规

 const int a = 12; int *p; p = &a; 

违反的约束是C11 6.5.16.1/1“简单分配”; 如果两个操作数都是指针,那么左边指向的类型必须具有右边指向的所有类型的限定符。 (并且类型,sans限定符,必须兼容)。

因此违反了约束,因为&a具有类型const int * ,其中const为限定符; 但是该限定符没有出现在int *的类型中。

编译器必须发出诊断信息,并且可能不会生成可执行文件。 任何可执行文件的行为都将完全未定义,因为该程序不符合该语言的规则。

是的,您可以更改常量变量的值。
试试这段代码:

 #include  int main() { const int x=10; int *p; p=(int*)&x; *p=12; printf("%d",x); }