Bin*_* Wu 1 c optimization gcc
我在GCC 4.8.2中遇到了一个奇怪的优化 - -O2,它删除了一个函数.
请参阅以下代码.
increase()和increase2()相同,只是后者有一个printf().
但是,如果在GCC中使用-O2,则会删除increase().
#include <stdio.h>
#include <stdint.h>
#include <arpa/inet.h>
void swap(uint64_t *vector)
{
uint32_t *p = (uint32_t *)vector;
uint32_t tmp = p[0];
p[0] = htonl(p[1]);
p[1] = htonl(tmp);
}
void increase(uint64_t *vector)
{
swap(vector);
(*vector)++;
swap(vector);
}
void increase2(uint64_t *vector)
{
swap(vector);
(*vector)++;
printf("touch...\n");
swap(vector);
}
int main()
{
uint64_t vector = 0xa;
increase(&vector);
printf("%lx\n", vector);
increase2(&vector);
printf("%lx\n", vector);
return 1;
}
Run Code Online (Sandbox Code Playgroud)
输出是:
a
touch...
10000000000000a
Run Code Online (Sandbox Code Playgroud)
为什么?
提前致谢
对不起,我没说清楚.
问题不在于"删除功能",而是"功能不会影响参数".
Matt McNabb指出了原因,即严格的混叠规则.非常感谢你.
此代码导致未定义的行为:
uint32_t *p = (uint32_t *)vector;
uint32_t tmp = p[0];
Run Code Online (Sandbox Code Playgroud)
指向的内存vector
是类型的对象uint64_t
,但是您通过类型的左值读取它uint32_t
.这违反了严格的别名规则.
由于您的程序始终调用此函数,因此未定义整个程序的行为.因此,当优化器切断导致UB的路径时,您可能会看到奇怪的优化工件.
另一个问题是你%lx
用来打印出来的uint64_t
.除非您的系统使用64位长,否则这将无效.要获得正确的说明符,请使用printf("%" PRIx64 "\n", vector);
.你可能需要#include <inttypes.h>
这个.
修复printf格式说明符后,我的系统会提供以下内容-O2
,或者使用-fno-strict-aliasing
开关:
10000000000000a
touch...
20000000000000a
Run Code Online (Sandbox Code Playgroud)
和垃圾在-O3
.
归档时间: |
|
查看次数: |
124 次 |
最近记录: |