rol*_*ack 5 c++ pointers const undefined-behavior
有人可以向我解释为什么这段代码有效吗?我觉得编译器不应该允许我做我做的事情(移动一个指针指向一个const int),或者我至少会期望编译器警告或段错误.改变常数值的想法似乎是错误的.
码:
#include <iostream>
using namespace std;
struct test_struct {
int i;
const int j;
};
int main() {
cout << "Create a struct with int i = 100 and const int j = 101." << endl;
test_struct test{100, 101};
cout << test.i << endl;
cout << test.j << endl;
cout << "Create pointer p and point it to int i." << endl;
int* p1 = &test.i;
cout << *p1 << endl;
cout << "Increment pointer p, which should now be pointing at const int j." << endl;
p1++;
cout << *p1 << endl;
cout << "Dereference p and increment it." << endl;
(*p1)++;
cout << *p1 << endl;
cout << test.j << endl;
}
Run Code Online (Sandbox Code Playgroud)
输出:
Create a struct with int i = 100 and const int j = 101.
100
101
Create pointer p and point it to int i.
100
Increment pointer p, which should now be pointing at const int j.
101
Dereference p and increment it.
102
102
Run Code Online (Sandbox Code Playgroud)
Sha*_*our 18
程序以两种方式调用未定义的行为,这意味着程序的行为是不可预测的,即使看似正常的行为也是可能的.
首先,虽然我们可以将结构的各个元素视为数组,但是一旦递增指针就不再有效取消引用它,它甚至不必指向它很可能指向填充的下一个元素.
其次,尝试在未定义的行为中改变const.该草案C++标准部7.1.6.1 的cv修饰符段4,其表示:
[...]任何在其生命周期内修改const对象的尝试(3.8)都会导致未定义的行为.
我们可以看到,为了指针运算的目的,非数组变量被视为一个元素的数组,来自5.7 Additive运算符,它说:
出于这些运算符的目的,指向非阵列对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型.
此外,从同一部分中取消引用一个数组末尾的未定义行为:
当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型.[...]如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义.
我们可以从一5.3.1 元运算符部分进一步看到:
一元*运算符执行间接:它所应用的表达式应该是指向对象类型的指针,或指向函数类型的指针,结果是引用对象或函数的左值
当我们取消引用我们期望的指针和我们不能保证的对象,一旦我们超过结束.
在GNU的C++库有一个更简单的访问说明它说(重点煤矿):
您只能取消引用指向数组的指针.如果你的数组指针指向数组外部 - 甚至只是一个结束 - 并且你取消引用它,就会发生糟糕的事情.
| 归档时间: |
|
| 查看次数: |
1757 次 |
| 最近记录: |