在以下代码中:

#include <stdio.h>

int main(void)
{
    int n = 74;
    int * pn = &n;

    short * sp;

    //sp = (short *)&n; // <-- bad
    sp = (short *)pn;   // <-- fine

    *sp = 4;
    printf("%d\n", *sp);

    return 0;
}

是否违反了严格的别名规则?据我所知,它是这样的,因为指向一个短指针指向一个int。但是编译器即使使用编译也不会抱怨(假设代码在test.c中)
gcc test.c -o test.exe -Wall -std=c99 -Wstrict-aliasing=2 -O3

但是,如果标记为bad的行未注释,而标记为fine的行被注释,则它确实会抱怨。
有人能解释一下这个案子真的违反了规则吗?如果是,为什么编译器没有检测到它?如果没有,为什么不呢,因为按照标准它应该吗?

最佳答案

编译器很难在编译时捕获冲突,除非您通过取消对不同类型的引用来分配新值,如下所示。如果您按如下所示更改代码,您将收到预期的警告。

int main(void)
{
    int n = 74;
    //int * pn = &n;

    //short * sp;

    //sp = (short *)&n; // <-- bad
    //sp = (short *)pn;   // <-- fine

    *((short*)&n) = 4;
    printf("%d\n", n);

    return 0;
}

这个问题显示了完全相同的问题,并提供了更多的细节。GCC: accuracy of strict aliasing warnings
蚂蚁的另一个回答是这样的:
“不是强制转换本身违反了严格的别名,而是随后的无效左值访问(内存重新解释)违反了它。”。。。。没错。我的示例尝试一个违反规则的左值访问,这样您就会得到警告。

关于c++ - 指针强制转换真的会破坏严格的别名吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44815927/

10-11 21:09