18

Can someone please explain to me the syntax of this function? where SYS_fork is some constant and sys_fork is a function.

static int (*syscalls[])(void) = {
[SYS_fork]    sys_fork,
[SYS_exit]    sys_exit,
[SYS_wait]    sys_wait,
[SYS_pipe]    sys_pipe,
[SYS_read]    sys_read,
[SYS_kill]    sys_kill,
[SYS_exec]    sys_exec,
};

Thank you!

2 Answers2

29

You've just encountered a use of designated initializers. They exist in C99 and are also available as a GCC extension, widely used in the Linux kernel code (among others).

From the docs:

In ISO C99 you can give the elements [of the array] in any order, specifying the array indices or structure field names they apply to, and GNU C allows this as an extension in C90 mode as well. [...]

To specify an array index, write ‘[index] =’ before the element value. For example,

int a[6] = { [4] = 29, [2] = 15 };

is equivalent to:

int a[6] = { 0, 0, 15, 0, 29, 0 };

[...]

An alternative syntax for this that has been obsolete since GCC 2.5 but GCC still accepts is to write ‘[index]’ before the element value, with no ‘=’.

In plain English, syscalls is a static array of pointer to function taking void and returning int. The array indices are constants and their associated value is the corresponding function address.

user703016
  • 37,307
  • 8
  • 87
  • 112
  • 5
    Wouldn't the code posted need `=`s signs based on that description? – Tommy Sep 24 '14 at 18:43
  • @dolan : Can you please explain how are SYS_fork, SYS_exit.....values acting as indexes ? :-) – Abhishek Choubey Sep 24 '14 at 20:19
  • 3
    @Abhishek They probably are defined elsewhere in the code. For example as an enumeration: `enum { SYS_fork, SYS_exit, ... };`. This creates a set of identifiers that behave as constants (0, 1, ...) that you can use as indices. It's also possible that they are defined as macros. – user703016 Sep 24 '14 at 20:30
  • 4
    @dolan From the link you posted: "An alternative syntax for this that has been obsolete since GCC 2.5 but GCC still accepts is to write `[index]` before the element value, with no `=`." – milleniumbug Sep 25 '14 at 00:26
  • @milleniumbug what exactly is obsolete? the mechanic it self or the one with(out) the `=`? – dhein Sep 25 '14 at 06:25
  • @Zaibis Obviously, the alternative syntax. I. e., the omitting of the `=`. – glglgl Sep 25 '14 at 07:29
1

You will know what's going on by running the following code:

#include <stdio.h>

void function_1(char *); 
void function_2(char *);
void function_3(char *);
void function_4(char *);

#define func_1    1
#define func_2    2
#define func_3    3
#define func_4    4

void (*functab[])(char *) = {       // pay attention to the order
    [func_2] function_2,
    [func_3] function_3,
    [func_1] function_1,
    [func_4] function_4
};

int main()
{
    int n;

    printf("%s","Which of the three functions do you want call (1,2, 3 or 4)?\n");

    scanf("%d", &n);

    // The following two calling methods have the same result

    (*functab[n]) ("print 'Hello, world'");  // call function by way of the function name of function_n

    functab[n] ("print 'Hello, world'");   // call function by way of the function pointer which point to function_n

    return 0;
}

void function_1( char *s) { printf("function_1 %s\n", s); }

void function_2( char *s) { printf("function_2 %s\n", s); }

void function_3( char *s) { printf("function_3 %s\n", s); }

void function_4( char *s) { printf("function_4 %s\n", s); }

result:

Which of the three functions do you want call (1,2, 3 or 4)?
1
function_1 print 'Hello, world'
function_1 print 'Hello, world'

 Which of the three functions do you want call (1,2, 3 or 4)?
 2
 function_2 print 'Hello, world'
 function_2 print 'Hello, world'

 Which of the three functions do you want call (1,2, 3 or 4)?
 3
 function_3 print 'Hello, world'
 function_3 print 'Hello, world'

 Which of the three functions do you want call (1,2, 3 or 4)?
 4
 function_4 print 'Hello, world'
 function_4 print 'Hello, world'
RecharBao
  • 371
  • 2
  • 10