为什么在函数名称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
正如您在6bb
和6c2
上看到的那样,test
的地址已通过相同的lea指令移至寄存器。此外,在6da
和6e6
上使用相同的lea指令。即使在机器代码级别上,使用或不使用&号似乎也没有任何区别。
答案 0 :(得分:3)
在表达式中使用时(不作为&
的操作数),任何函数类型的表达式(例如您的示例中的test
)都会自动转换为函数的地址。 / p>
这由C standard的6.3.2.1p4节规定:
函数指示符是具有函数类型的表达式。 除非它是
sizeof
运算符的操作数,否则_Alignof
运算符或一元&
运算符,类型为“ function returning type”的函数指示符将转换为表达式 类型为“函数返回类型的指针”的类型。
&test
和test
的计算结果相同,*test
,**test
,***test
等也是如此。