C++ const通过指针改变了,还是它?

gra*_*tot 16 c c++ pointers const

在c中,可以使用像这样的指针来改变const:

//mainc.c
#include <stdio.h>

int main(int argc, char** argv) {
    const int i = 5;
    const int *cpi = &i;

    printf("  5:\n");
    printf("%d\n", &i);
    printf("%d\n", i);
    printf("%d\n", cpi);    
    printf("%d\n", *cpi);   

    *((int*)cpi) = 8;
    printf("  8?:\n");
    printf("%d\n", &i);
    printf("%d\n", i);
    printf("%d\n", cpi);
    printf("%d\n", *cpi);
}
Run Code Online (Sandbox Code Playgroud)

从输出中可以看出常量已更改: mainc输出

如果我们在c ++中尝试相同:

//main.cpp
#include <iostream>

using std::cout;
using std::endl;

int main(int argc, char** argv) {
    const int i = 5;
    const int *cpi = &i;

    cout << "  5:" << '\n';
    cout << &i << '\n';
    cout << i << '\n';
    cout << cpi << '\n';    
    cout << *cpi << '\n';   

    *((int*)cpi) = 8;
    cout << "  8?:" << '\n';
    cout << &i << '\n';
    cout << i << '\n';
    cout << cpi << '\n';
    cout << *cpi << '\n';

    int* addr = (int*)0x28ff24;
    cout << *addr << '\n';
}
Run Code Online (Sandbox Code Playgroud)

结果不太清楚: 主要产出

从输出看起来i仍然5是仍然位于0x28ff24所以const不变.但同时cpi也是0x28ff24(相同&i),但它指出的价值是8(不是5).

有人可以解释一下这里发生了什么样的魔法?

在此解释:https://stackoverflow.com/a/41098196/2277240

Bat*_*eba 34

抛弃const最初声明为变量(甚至通过C++中的指针或引用),const然后尝试通过该指针或引用更改变量的行为是未定义的.

因此,i如果它被声明为更改const int i = 5;是未定义的行为:您正在观察的输出是其表现形式.

  • 为了超级迂腐,抛弃`const`很好,但实际上修改对象是UB.这种情况可能出现在一些通用代码中. (12认同)
  • @grabantot:如果你的程序调用了未定义的行为,那么你根本不能信任任何*.在调用未定义的行为之前,你甚至不能相信你认为发生的事情! (8认同)
  • @grabantot未定义的行为意味着任何事情都可能发生.编译器甚至不必对"任何东西"的定义保持一致!不仅在代码的那一行,任何调用未定义行为的程序都会中毒整个运行.这背后的基本原理是允许实现在不应该发生的情况下做"最便宜"的任何事情,从而允许进行优化.永远不要修改最初声明为const的变量! (2认同)

Lun*_*din 15

根据C11 6.7.3/6,它是未定义的行为:

如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为是未定义的.

(C++将有类似的规范性文本.)

由于它是未定义的行为,任何事情都可能发生.包括:奇怪的输出,程序崩溃,"似乎工作正常"(这个版本).