提问者:小点点

当使用char类型的glvalue访问另一种类型的对象时,是否不需要得到UB


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]),则该行为未定义:

  • 字符、无符号字符或std::byte类型。

它似乎也没有违反以下规则:
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个答案

匿名用户

这是否意味着#1处的片段不会导致UB?

是的,引用的规则意味着#1的定义很好。

2号应该是UB对吧?

不,根据引用的规则,#2的行为也有很好的定义。

ptr的类型是char*,因此*ptr表达式的类型是char,其值不能超过char表示的值,因此expr#pre-4不适用。

假设测试环境中字符的宽度为8位,其范围为[-128,127]。

为了很好地定义#1,这个假设并不是必要的。

v的值为1

这并不是仅仅从上述假设中得出的。虽然标准没有确切地指定表示形式,但如果CPU有一个小的endian(包括前面的假设),这实际上是正确的。