int main(){
int v = 1;
char* ptr = reinterpret_cast<char*>(&v);
char r = *ptr; //#1
}
在此片段中,表达式ptr指向一个int类型的对象,如:
expr.static.cast#13所示
否则,指针值将通过转换保持不变。
间接ptr
将产生一个glvalue,该glvalue表示ptr
指向的对象,如
expr.unary#op-1所示
结果是一个L值,它引用表达式所指向的对象或函数。
根据
basic.lval#11,使用允许类型的glvalue访问对象不会导致UB
如果程序试图通过glvalue访问([defns.access])对象的存储值,而glvalue的类型与下列类型之一不相似([conv.qual]),则该行为未定义:
它似乎也没有违反以下规则:
expr#pre-4
如果在计算表达式的过程中,结果未在数学上定义或不在其类型的可表示值范围内,则该行为未定义。
假设测试环境中char
的宽度为8位,其范围为[-128,127]。v
的值为1。那么,这是否意味着#1
处的片段不会导致UB?
作为对比,给出以下示例
int main(){
int v = 2147483647; // or any value greater than 127
char* ptr = reinterpret_cast<char*>(&v);
char r = *ptr; //#2
}
#2
应该是UB,对吗?
这是否意味着#1处的片段不会导致UB?
是的,引用的规则意味着#1的定义很好。
2号应该是UB对吧?
不,根据引用的规则,#2的行为也有很好的定义。
ptr
的类型是char*
,因此*ptr
表达式的类型是char
,其值不能超过char
表示的值,因此expr#pre-4不适用。
假设测试环境中字符的宽度为8位,其范围为[-128,127]。
为了很好地定义#1,这个假设并不是必要的。
v的值为1
这并不是仅仅从上述假设中得出的。虽然标准没有确切地指定表示形式,但如果CPU有一个小的endian(包括前面的假设),这实际上是正确的。