我们是否违反了严格别名规则?

mas*_*cai 4 c++ strict-aliasing language-lawyer

这段代码中是否存在严格别名规则违规?我认为int->charint->std::byte都可以,但是呢int8_t

int main() {
    int arr[8] = {1, 1, 1, 1, 1, 1, 1, 1}; // Little endian: 10000000 | 10000000 ....
    int8_t *ptr = (int8_t*)arr; // Do we have a violation of the Strict Aliasing rule in this cast?
    ptr += 3; // 100[0]0000 ....

    cout << (int)*ptr << endl; // outputs 0
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

Jan*_*tke 8

\n
int8_t *ptr = (int8_t*)arr;\n
Run Code Online (Sandbox Code Playgroud)\n
\n

这完全没问题,相当于reinterpret_cast.\n强制转换本身从来都不是严格的别名冲突;所指向对象的访问权限是。请参阅什么是严格的别名规则?更多细节。

\n
\n
cout << (int)*ptr << endl; // outputs 0\n
Run Code Online (Sandbox Code Playgroud)\n
\n

这是未定义的行为 ( [basic.lval] p11int ),因为您正在通过 类型的泛左值访问 an int8_t。\n只有 、 和 的例外charunsigned char并且std::byteint8_t可能是 的别名signed char

\n
\n
ptr += 3;\n
Run Code Online (Sandbox Code Playgroud)\n
\n

这是未定义的行为:

\n
\n

对于加法或减法,如果表达式 P 或 Q 的类型为 \xe2\x80\x9c 指向 cv T\xe2\x80\x9d 的指针,其中 T 和数组元素类型不相似,则行为未定义。
\n[示例 1 :

\n
int arr[5] = {1, 2, 3, 4, 5};\nunsigned int *p = reinterpret_cast<unsigned int*>(arr + 1);\nunsigned int k = *p;            // OK, value of k is 2 ([conv.lval])\nunsigned int *q = p + 1;        // undefined behavior: p points to an int, not an unsigned int object\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x80\x94结束示例]

\n
\n

- [expr.add] p6

\n

您所做的实际上是相同的,只是使用int8_t而不是unsigned int.

\n
\n

我是这么想的int -> charint -> std::byte但是那又怎样呢int8_t

\n
\n

强制转换本身总是好的,但只有std::bytechar具有也使(1)p += 3有效的特殊属性。

\n

int8_t很可能是 的别名,与和signed char相比,它的魔力要少得多。\n有关魔力的摘要,请参阅此答案的附录。unsigned charstd::byte

\n
\n

(一)标准措辞有缺陷且不支持的;请参阅添加到“char *”指针 UB,但它实际上并未指向 char 数组?

\n