数组中的严格别名规则

时间:2014-11-19 19:42:03

标签: c++ strict-aliasing

此代码片段是否违反严格别名规则:

int main()
{
    short tab[] = {1,2,3,4};
    int* ps = (int*)(&tab[0]);
    int i = *ps;
}

我知道,如果这是违反相反的行为,那将是违规行为

int main()
{
    int tab[] = {1,2,3,4};
    short* ps = (short*)(&tab[0]);
    short s = *ps;
}

3 个答案:

答案 0 :(得分:2)

指向另一个(任意)指针类型的指针,只要它不是格式错误,不构成违规;但是在取消引用该指针后访问pointees值将是。

你的演员阵容相当于reinterpret_cast,[expr.reinterpret.cast] / 7:

  

可以将对象指针显式转换为对象指针   不同的类型。当“指向T1的指针”类型的prvalue v时   转换为“指向 cv T2的指针”,结果为static_cast< cv   如果T2*>(static_cast<void*>(v))都是标准布局,则T1 cv T2   类型(3.9)和T2的对齐要求并不比。{更严格   那些T1,或者任何一种类型都是无效的。

答案 1 :(得分:2)

当然违反了严格的别名。代码通过不同类型的指针访问值,并且它不是char*

int main()
{
    short tab[] = {1,2,3,4};
    int* ps = (int*)(&tab[0]);
    *ps = 3;
    if(tab[0] == 1) return 1;
    return 0;
}

允许代码在那里返回1。因为写入* ps是对int的写入,并且根据严格的别名规则,int指针不可能指向short。因此,允许优化器看到tab数组未被修改,优化if语句,因为它总是为真,并重写整个函数只返回1.

答案 2 :(得分:0)

如果您尝试取消引用转换后的指针,则在两种情况下都会得到未定义的行为。

非正式地说,这是因为类型的对齐方式可能不同。

使用联盟;较长的类型和较短类型的数组是一种安全的数据转换方式。