Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
gcc和clang不愿意懒散地初始化部分使用的结构_C_Gcc_Clang_Compiler Optimization_Compiler Bug - Fatal编程技术网

gcc和clang不愿意懒散地初始化部分使用的结构

gcc和clang不愿意懒散地初始化部分使用的结构,c,gcc,clang,compiler-optimization,compiler-bug,C,Gcc,Clang,Compiler Optimization,Compiler Bug,考虑以下代码: __attribute__((noinline)) int foo1(int x, int y) { return x; } int bar1(int* a) { int b = foo1(a[5], a[10]); return b * b; } 即使foo1没有内联,编译器也可以很容易地判断出它的一个参数未使用;所以实际上没有必要去初始化它。实际上,GCC 8.2和clang 7.0都编译bar1(),以便只从内存中读取第一个参数的值 现在假设我们

考虑以下代码:

__attribute__((noinline)) int foo1(int x, int y)
{
    return x;
}

int bar1(int* a)
{
    int b = foo1(a[5], a[10]);
    return b * b;
}
即使
foo1
没有内联,编译器也可以很容易地判断出它的一个参数未使用;所以实际上没有必要去初始化它。实际上,GCC 8.2和clang 7.0都编译
bar1()
,以便只从内存中读取第一个参数的值

现在假设我们将这两个int参数放入一个结构中:

struct two_ints { int x, y; };

__attribute__((noinline)) int foo2(struct two_ints s)
{
    return s.x;
}

int bar2(int* a)
{
    struct two_ints ti = { a[5], a[10] };
    int b = foo2(ti);
    return b * b;
}
应该没什么区别吧?参数(当然就组件而言)是两个整数;第二个是不使用的。所以我希望看到相同的汇编代码。然而我不。在调用
foo2()
之前,clang和gcc都会初始化
ti
的两个字段

(GodBolt.org)


那么,编译器是否有义务初始化这两个字段,或者这是一个错过的优化机会?

编译器可以分析
foo1
,并决定在调用函数的任何地方抑制第二个参数。但在第二种情况下,编译器需要分析整个程序,然后才能安全地抑制第二个初始值设定项。
foo2
不使用member
y
这一事实并不能告诉编译器是否需要
ti.y
。@user3386109:这不是真的。编译器不需要全局抑制第二个初始值设定项。它只需要在
foo2()
中抑制它。我被以下语句误导了:“在调用
foo2()
之前,clang和gcc都初始化
ti
的两个字段。”。似乎您实际上关心的是
s
的初始化,它是传递给
foo2
@user3386109的
ti
的副本:
ti
被省略在
foo2()的输入参数中。只有一个结构。编译器可以分析
foo1
,并决定在调用函数的任何地方抑制第二个参数。但在第二种情况下,编译器需要分析整个程序,然后才能安全地抑制第二个初始值设定项。
foo2
不使用member
y
这一事实并不能告诉编译器是否需要
ti.y
。@user3386109:这不是真的。编译器不需要全局抑制第二个初始值设定项。它只需要在
foo2()
中抑制它。我被以下语句误导了:“在调用
foo2()
之前,clang和gcc都初始化
ti
的两个字段。”。似乎您实际上关心的是
s
的初始化,它是传递给
foo2
@user3386109的
ti
的副本:
ti
被省略在
foo2()的输入参数中。只有一个结构。