c++ 在cpp中创建一个变量const,然后将它的地址给一个指针,但是解引用并没有改变变量,为什么?

niwlg2el  于 2023-05-20  发布在  其他
关注(0)|答案(2)|浏览(127)

在cpp中创建一个变量const,然后将它的地址给一个指针,并通过取消引用来改变它的值,但我仍然得到了我最初存储的值。
代码片段

const int a = 5;
    // then
    // a = 7; not possible
    // bypassing const using pointers
    int *ap = (int *)&a;
    *ap = 10;

    cout << *ap <<" "<< *(&a)<<" " << a << endl;

输出为:

jc3wubiy

jc3wubiy1#

任何修改声明为const的变量或成员的程序都具有C标准不再定义的行为。
这被称为UB。UB的常见症状是崩溃,“它似乎工作”,wierd不一致的状态,甚至时间旅行,未来的UB改变行为 * 之前 * 它发生在你的代码中。
一个好的C
程序员会有一些不太可能使用UB的习惯。
你在这里看到的UB的症状是,因为没有一个程序的行为是由C标准指定的,const int x=5;可以有除了5之外的任何值,编译器用常量5替换对x的读取。
另一方面,您可以形成指向x的指针,并且x在那里确实有字节。编译器可以自由地将x放在ROM或受保护的页面中,或者它可以不打扰并将其放在普通内存中。
您将形成指向x的指针。编译器不会省略这个指针(允许这样做,但也允许不这样做),因此在您的机器码中,它实际上读取和写入存储x的地址处的数据。因此,*&x10,而x5。此外,如果编译器优化指针,*&x可能是5
避免UB。
C
定义了一个抽象机器,C程序有定义在其上的行为(除非你做UB)。然后将其转换为保证与抽象机器行为一致的机器代码,但根本不能保证看起来“应该”Map到某些机器代码的C代码。
这种抽象与具体之间的差距允许大量的优化。
C++抽象的机器行为被设计成 * 容易 * Map到机器代码,UB被留在强制执行某些行为会有成本的地方。

4zcjmb1e

4zcjmb1e2#

它已经得到了完美的回答--修改const是未定义的行为,试图破译未定义的行为是没有意义的,因为它取决于编译器的内部设计,而不是任何标准。
但是有一个标准的方法来绕过const:const_cast关键字例如,如果某个函数的输入参数不需要常量,但您的输入是常量,则可以使用它。然而,即使在抛弃了常数之后,修改仍然会导致未定义的行为!

相关问题