严格别名警告在gcc 4.6.1中出现的错误

6

我试图在gcc上用-pedantic-errors -pedantic -Wall -O2编译以下内容。

#include <iostream>

void reset_uint32(uint32_t* pi)
{
    char* c = (char*)(pi);
    uint16_t* j = (uint16_t*)(c); // warning?
    j[0] = 0;
    j[1] = 0;
}

void foo()
{
    uint32_t i = 1234;
    reset_uint32(&i);
}

int main() {
   foo();
}

但我没有看到任何严格别名警告。 我也尝试启用。
-fstrict-aliasing
-Wstrict-aliasing

但仍然没有警告。这是一个错误吗?

1
你试图做的事情没有任何意义。为什么不直接执行 *pi = 0 - Pubby
4
@Pubby: 可能这只是一个人为制造的最小化测试案例... - Oliver Charlesworth
2
@Omnifarious:严格别名规则允许通过char*进行别名访问,但不允许通过该char*类型进行 '重新别名化' 到另一种类型。但就我所知,这可能会导致警告被禁用,无论是有意还是无意地。 - Michael Burr
1
首先,别名规则允许将指针转换为和从 char * 转换。但是,别名规则既不允许也不禁止任何指针转换。 - curiousguy
1
@MichaelBurr说:“但不允许're-aliasing'”,这里没有“重新别名”,而且这些规则也没有涉及指针转换。别名规则是关于lvalue的使用的规则。 - curiousguy
显示剩余5条评论
1个回答

1

我重写了你的示例,以产生有关违反严格别名规则的警告:

void foo(int* pi) {
    short* j = (short*)pi;
    j[0] = j[1] = 0;
}

int main() {
    int i = 1234;

    foo(&i);

    short* j = (short*)&i;
    j[0] = j[1] = 0;
}

尽管如此,g++ 4.6仅在使用-Wstrict-aliasing=2而不是-Wstrict-aliasing编译代码时才显示警告。此外,它仅在main()中的转换中显示警告,而不是在foo()中。但我无法看出编译器为什么会以不同的方式查看这两个转换。

“-Wstrict-aliasing=2”和“-Wstrict-aliasing”有什么区别? - user1086635
据说严格别名检测的三个级别通过对代码进行更详细的分析,其误报率逐渐降低。1是最糟糕的级别,误报率最高,而3是最好的级别,误报率最低。在我自己尝试不同级别时,似乎级别3也有很高的漏报率。 - Omnifarious
但我看不出编译器为什么会以不同的方式查看这两个转换。因为在main中,编译器知道变量的声明类型。 - curiousguy
1
@user1086635:这是关于-Wstrict-aliasing警告的当前文档:http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wstrict_002daliasing_003dn-347 - Omnifarious

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接