6

我可以const在 gcc 中更改已修改变量的值,但不能在其他编译器中更改。我在 gcc 上尝试过这段代码,它更新了iand j(11) 的值。使用在线编译器,我得到不同的值。

#include<stdio.h>
void main() {
  const int i=10;
  int *j;
  j = &i;
  (*j)++;
  printf("address of j is %p address of i is %p\n",j,&i);
  printf("i is %d and j is %d\n",i,*j);
}
4

5 回答 5

19

是的,你可以用一点技巧来做到这一点。

#include <stdio.h>
int main(){
    const int a = 0;
    *(int *)&a = 39;
    printf("%d", a);
}

在上面的代码中,a是一个const int. 使用小技巧,您可以更改常量值。

更新:说明

在上面的代码中, a 被定义为 a const。例如 a 有一个内存地址0x01,因此&a返回相同的地址。当它被强制转换时,(int *)它成为另一个变量,称为指向 const 的指针。当*再次访问时,另一个变量可以在不违反 const 策略的情况下被访问,因为它不是原始变量,但由于它被称为指针的地址,因此更改会被反映。

这将适用于 Borland C++ 或 Turbo C++ 等旧版本,但是现在没有人使用它。

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

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

然而,在某些情况下——最常见的是 const 静态数据——编译器可能会将这些变量放在内存的只读区域中。例如,MSVC 通常会将 const static ints 放在可执行文件的 .text 段中,这意味着如果您尝试对其进行写入,操作系统将抛出保护错误,并且程序将崩溃。

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

试试这个,让我知道。

于 2015-07-23T09:35:20.190 回答
9

如何修改 const 变量的值?

不!您不应该修改const变量。
拥有const变量的全部意义在于不能修改它。如果您想要一个应该能够修改的变量,只需不要const在其上添加限定符。

任何const通过(指针)hackery 强制修改的代码都会调用Undefined Behavior

未定义行为意味着代码不符合 C 标准制定的标准规范,因此不是有效代码。这样的代码可以显示任何行为,并且允许这样做。

于 2012-08-24T07:27:48.930 回答
7

通过定义iconst,您承诺不修改它。编译器可以依赖该承诺并假设它没有被修改。当您打印 的值时i,编译器可以只打印10而不是加载当前存储在 中的任何值i

或者它可以选择加载值。或者,当您尝试修改i. 行为未定义。

-O1根据优化选项 ( , -O3) ,您可能会看到 gcc 的不同行为。

哦,而且void main()是不正确的;它应该是int main(void)。如果你的教科书告诉你使用void main(),你应该得到一本更好的书。

于 2012-08-24T07:35:35.537 回答
2

看看我们能不能通过指针改变一个用const定义的对象的值?

长话短说,它是一个undefined behaviour. 它可能取决于编译器/机器。

于 2012-08-24T07:35:28.517 回答
0

如果您在 gcc 中编译此代码,则无法修改const变量的值,它将显示

error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]

并显示未定义的行为

主要是我们只能修改变量,当我们可以访问没有地址的地址时我们什么都做不了。这与注册存储类相同。

于 2013-10-06T03:16:28.667 回答