在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;
输出为:
十
2条答案
按热度按时间jc3wubiy1#
任何修改声明为
const
的变量或成员的程序都具有C标准不再定义的行为。这被称为UB。UB的常见症状是崩溃,“它似乎工作”,wierd不一致的状态,甚至时间旅行,未来的UB改变行为 * 之前 * 它发生在你的代码中。
一个好的C程序员会有一些不太可能使用UB的习惯。
你在这里看到的UB的症状是,因为没有一个程序的行为是由C标准指定的,
const int x=5;
可以有除了5
之外的任何值,编译器用常量5
替换对x
的读取。另一方面,您可以形成指向
x
的指针,并且x
在那里确实有字节。编译器可以自由地将x
放在ROM或受保护的页面中,或者它可以不打扰并将其放在普通内存中。您将形成指向
x
的指针。编译器不会省略这个指针(允许这样做,但也允许不这样做),因此在您的机器码中,它实际上读取和写入存储x
的地址处的数据。因此,*&x
是10
,而x
是5
。此外,如果编译器优化指针,*&x
可能是5
。避免UB。
C定义了一个抽象机器,C程序有定义在其上的行为(除非你做UB)。然后将其转换为保证与抽象机器行为一致的机器代码,但根本不能保证看起来“应该”Map到某些机器代码的C代码。
这种抽象与具体之间的差距允许大量的优化。
C++抽象的机器行为被设计成 * 容易 * Map到机器代码,UB被留在强制执行某些行为会有成本的地方。
4zcjmb1e2#
它已经得到了完美的回答--修改const是未定义的行为,试图破译未定义的行为是没有意义的,因为它取决于编译器的内部设计,而不是任何标准。
但是有一个标准的方法来绕过const:const_cast关键字例如,如果某个函数的输入参数不需要常量,但您的输入是常量,则可以使用它。然而,即使在抛弃了常数之后,修改仍然会导致未定义的行为!