gcc 和 clang 发出看似多余的函数调用

问题描述 投票:0回答:1
typedef struct foo
{
    void (*const t)(struct foo *f);
} foo;

void t(struct foo *f)
{
    
}

void (*const myt)(struct foo *f) = t;

foo f = {.t = t};

int main(void)
{
    f.t(&f);
    myt(&f);

    return 0;
}

使用 x86-64 gcc 13.2 和 clang 16.0.0 编译上述代码时,会生成类似的汇编代码。下面显示的是 gcc 输出。

t:
        ret
main:
        sub     rsp, 8
        mov     edi, OFFSET FLAT:f
        call    [QWORD PTR f[rip]]
        xor     eax, eax
        add     rsp, 8
        ret
f:
        .quad   t
myt:
        .quad   t

为什么两个编译器在通过

t
调用时都会发出对
struct foo
函数的调用,而在通过
myt
函数指针调用时却不会?为什么编译器无法看到
t
中的
struct foo
函数指针指向空函数并消除所有调用?由于
f
是静态分配的,并在编译时初始化,因此它的成员
t
(一个在运行时无法更改的常量指针(不调用未定义的行为))指向一个空函数
t

c gcc clang function-pointers
1个回答
0
投票

由于

f
不是 const 限定的 complete 对象 (cf. [basic.life]/10),它可以被销毁并通过放置 new 重新创建,另一个翻译单元可能会在初始化程序之前执行此操作
main
开始。这不仅对于
myt
来说是不可能的,而且它甚至具有内部链接,因此其他翻译单元根本无法引用它。

© www.soinside.com 2019 - 2024. All rights reserved.