为什么在函数名称上使用与号?

时间:2019-02-02 23:00:31

标签: c

为什么在函数名称https://elixir.bootlin.com/linux/v4.0/source/arch/x86/kernel/traps.c#L991上使用与号?符号system_call是一个函数,因此变量的内容已经是一个内存地址。为什么用&号表示地址?例如,我编写了以下测试程序:

#include <stdio.h>

int receiver(void *);

int test() {
}

int main() {
        printf("%p %p\n", test, &test);
        receiver(test);
        receiver(&test);
}

int receiver(void *p) {
        printf("receiver %p\n", p);
}

输出为:

0x556baeada6b0 0x556baeada6b0
receiver 0x556baeada6b0
receiver 0x556baeada6b0

使用&号似乎没有任何作用。

更多,如果我使用

objdump -d .text test

这是结果:

00000000000006b7 <main>:
 6b7:   55                      push   %rbp
 6b8:   48 89 e5                mov    %rsp,%rbp
 6bb:   48 8d 15 ee ff ff ff    lea    -0x12(%rip),%rdx        # 6b0 <test>
 6c2:   48 8d 35 e7 ff ff ff    lea    -0x19(%rip),%rsi        # 6b0 <test>
 6c9:   48 8d 3d d4 00 00 00    lea    0xd4(%rip),%rdi        # 7a4 <_IO_stdin_used+0x4>
 6d0:   b8 00 00 00 00          mov    $0x0,%eax
 6d5:   e8 86 fe ff ff          callq  560 <printf@plt>
 6da:   48 8d 3d cf ff ff ff    lea    -0x31(%rip),%rdi        # 6b0 <test>
 6e1:   e8 13 00 00 00          callq  6f9 <receiver>
 6e6:   48 8d 3d c3 ff ff ff    lea    -0x3d(%rip),%rdi        # 6b0 <test>
 6ed:   e8 07 00 00 00          callq  6f9 <receiver>
 6f2:   b8 00 00 00 00          mov    $0x0,%eax
 6f7:   5d                      pop    %rbp
 6f8:   c3                      retq

正如您在6bb6c2上看到的那样,test的地址已通过相同的lea指令移至寄存器。此外,在6da6e6上使用相同的lea指令。即使在机器代码级别上,使用或不使用&号似乎也没有任何区别。

1 个答案:

答案 0 :(得分:3)

在表达式中使用时(不作为&的操作数),任何函数类型的表达式(例如您的示例中的test)都会自动转换为函数的地址。 / p>

这由C standard的6.3.2.1p4节规定:

  

函数指示符是具有函数类型的表达式。   除非它是sizeof运算符的操作数,否则   _Alignof运算符或一元&运算符,类型为“ function returning type”的函数指示符将转换为表达式   类型为“函数返回类型的指针”的类型。

&testtest的计算结果相同,*test**test***test等也是如此。