2

Why do we use an ampersand on a function name: https://elixir.bootlin.com/linux/v4.0/source/arch/x86/kernel/traps.c#L991? The symbol system_call is a function so the content of the variable is already a memory address. Why taking it's address with ampersand? For example, I wrote this test program:

#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);
}

The output is:

0x556baeada6b0 0x556baeada6b0
receiver 0x556baeada6b0
receiver 0x556baeada6b0

Using ampersand doesn't seem to do anything.

Further more, if I use

objdump -d .text test

Here is the result:

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

As you can see on both 6bb and 6c2 the address of test is moved to a register with the same lea instruction. Besides, on 6da and 6e6 the same lea instruction are used. Using the ampersand or not doesn't seem to make any difference even on the machine code level.

darklord
  • 5,077
  • 12
  • 40
  • 65
  • Possible duplicate of [Why do function pointer definitions work with any number of ampersands '&' or asterisks '\*'?](https://stackoverflow.com/questions/6893285/why-do-function-pointer-definitions-work-with-any-number-of-ampersands-or-as) (While it doesn't technically answer _why_ the author of the code you linked to chose to use an `&` instead of omitting it, that question may not be answerable except by finding the author and asking them.) – Ilmari Karonen Feb 02 '19 at 23:12

1 Answers1

3

When used in an expression (other than as the operand of &), any expression of function type (such as test in your example) is automatically converted to the address of the function.

This is dictated in section 6.3.2.1p4 of the C standard:

A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".

So &test and test evaluate to the same thing, as does *test, **test, ***test, etc.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Then for this case https://elixir.bootlin.com/linux/v4.0/source/arch/x86/kernel/traps.c#L991, it is just a personal preference to use ampersand on a function name? – darklord Feb 02 '19 at 23:11
  • @darklord Basically, yes. The ampersand can be used but is not required. – dbush Feb 02 '19 at 23:16