I was examining some code on github https://github.com/umlaeute/v4l2loopback/blob/master/v4l2loopback.c and came across this line, which baffles me. Is this some incredibly cool kernel macro or gcc feature that I don't know about? What does the = -1 do?
static int video_nr[MAX_DEVICES] = { [0 ... (MAX_DEVICES-1)] = -1 };
module_param_array(video_nr, int, NULL, 0444);
MODULE_PARM_DESC(video_nr, "video device numbers (-1=auto, 0=/dev/video0, etc.)");
The line in question is the first, the next two given for context (this is creating a cmdline-specifiable parameter using a kernel macro http://lxr.free-electrons.com/source/include/linux/moduleparam.h#L103 )
Anyway, what is going on with the array initialization? How does that syntax work?
You've found an example of designated initializers. C99 & C11 don't go quite as far as your example, but they have some pretty flexible support for this kind of behaviour. Your specific example (using the ...) is a GCC extension. From the link:
To initialize a range of elements to the same value, write [first ... last] = value. This is a GNU extension. For example,
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
So that means your example is creating an array of size MAX_DEVICES and initializing every element in that array to -1.
For reference, the only standard-supported behaviour is to assign specific indices, rather than ranges:
[constant-expression] = initializer-value
There is a more complicated example in my copy of the spec:
int a[MAX] = {
1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
};
Which initializes the first five and last five elements of the array to explicit values. The middle values (if any) would be 0.
Related
static uint8_t togglecode[256] = {
[0x3A] CAPSLOCK,
[0x45] NUMLOCK,
[0x46] SCROLLLOCK
};
What's the meaning of [0x3A] here? I have only learned statements like int a[2] = {1, 2};
It means initialise the n-th element of the array. The example you've given will mean that:
togglecode[0x3A] == CAPSLOCK
togglecode[0x45] == NUMLOCK
togglecode[0x46] == SCROLLLOCK
These are called "designated initializers", and are actually part of the C99 standard. However, the syntax without the = is not. From that page:
An alternative syntax for this which has been obsolete since GCC 2.5 but GCC still accepts is to write [index] before the element value, with no =.
According to the GCC docs this is ISO C99 compliant. They refer to it as "Designated Initializers":
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 };
I've never seen this syntax before, but I just compiled it with gcc 4.4.5, with -Wall. It compiled successfully and gave no warnings.
As you can see from that example, it allows you to initialize specific array elements, with the others being set to their default value (0).
That was introduced in C99 and it's called a designated initialiser.
It basically allows you to set specific values in an array with the rest left as defaults.
In this particular case, the array indexes are the keyboard scan codes. 0x3a is the scan code in set #1 (see section 10.6) for the CapsLock key, 0x45 is NumLock and 0x46 is ScrollLock.
On the first link above, it states that:
int a[6] = { [4] = 29, [2] = 15 };
is equivalent to:
int a[6] = { 0, 0, 15, 0, 29, 0 };
Interestingly enough, though the link states that = is necessary, that doesn't appear to be the case here. That's not part of the standard but is a hangover from a rather old version of gcc.
It's (close to) the syntax of designated initializers, a C99 feature.
Basically, it initializes parts of an array, for example;
int aa[4] = { [2] = 3, [1] = 6 };
Intializes the second value of the array to 6, and the third to 3.
In your case the array offsets happen to be in hex (0x3a) which initializes the 58'th element of the array to the value of CAPSLOCK which presumably is defined in the code above the code you're showing.
The version in your code without the = seems to be a gcc specific extension.
I was reading bootloader code of some OS and came up with such syntaxt:
pde_t entry_pgdir[NPDENTRIES] = {
// Map VA's [0, 4MB) to PA's [0, 4MB)
[0]
= ((uintptr_t)entry_pgtable - KERNBASE) + PTE_P,
// Map VA's [KERNBASE, KERNBASE+4MB) to PA's [0, 4MB)
[KERNBASE>>PDXSHIFT]
= ((uintptr_t)entry_pgtable - KERNBASE) + PTE_P + PTE_W
};
What does it mean — [0] = …?
This is C99 array initialization syntax (aka ‘designated initializer’). It lets you mix regular values, e.g.
pde_t entry_pgdir[NPDENTRIES] = {val1, val2}
with [ind1] = val1, [ind2] = val2 syntax. The semantics of this is that the value in square brackets is interpreted as an index, and the value after = is interpreted as the value to store at the corresponding index.
The remaining entries are zeroed out. If you put regular values after an indexed one, the numbering continues at index+1.
This syntax is convenient when the data has gaps, for example
int logval[] = {
[1<<0] = 1
, [1<<1] = 2
, [1<<2] = 3
, [1<<3] = 4
...
};
This is easier to read than its plain equivalent:
int logval[] = {0, 1, 2, 0, 3, 0, 0, 0, 4, ...}
what does it mean? [0] = smth?
It's a designated initializer. A C99 construct that allows you to specify the array element which will be initialized with smth. So one does not have to rely on the position of the initializer to match that of the array element implicitly. Instead the initialization is made explicit (and IMO that's better).
It is called a "designated initializer". It means that the following initializer is for the first element of the array (index 0). In this case, it is redundant, because the first initializer would be for the first element anyway. It is here to provide parallelism with the second initializer, which has [KERNBASE>>PDXSHIFT] as the designator.
The initializer as a whole provides an initial value for 2 of the array elements. The rest of the array is initialized to 0.
static uint8_t togglecode[256] = {
[0x3A] CAPSLOCK,
[0x45] NUMLOCK,
[0x46] SCROLLLOCK
};
What's the meaning of [0x3A] here? I have only learned statements like int a[2] = {1, 2};
It means initialise the n-th element of the array. The example you've given will mean that:
togglecode[0x3A] == CAPSLOCK
togglecode[0x45] == NUMLOCK
togglecode[0x46] == SCROLLLOCK
These are called "designated initializers", and are actually part of the C99 standard. However, the syntax without the = is not. From that page:
An alternative syntax for this which has been obsolete since GCC 2.5 but GCC still accepts is to write [index] before the element value, with no =.
According to the GCC docs this is ISO C99 compliant. They refer to it as "Designated Initializers":
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 };
I've never seen this syntax before, but I just compiled it with gcc 4.4.5, with -Wall. It compiled successfully and gave no warnings.
As you can see from that example, it allows you to initialize specific array elements, with the others being set to their default value (0).
That was introduced in C99 and it's called a designated initialiser.
It basically allows you to set specific values in an array with the rest left as defaults.
In this particular case, the array indexes are the keyboard scan codes. 0x3a is the scan code in set #1 (see section 10.6) for the CapsLock key, 0x45 is NumLock and 0x46 is ScrollLock.
On the first link above, it states that:
int a[6] = { [4] = 29, [2] = 15 };
is equivalent to:
int a[6] = { 0, 0, 15, 0, 29, 0 };
Interestingly enough, though the link states that = is necessary, that doesn't appear to be the case here. That's not part of the standard but is a hangover from a rather old version of gcc.
It's (close to) the syntax of designated initializers, a C99 feature.
Basically, it initializes parts of an array, for example;
int aa[4] = { [2] = 3, [1] = 6 };
Intializes the second value of the array to 6, and the third to 3.
In your case the array offsets happen to be in hex (0x3a) which initializes the 58'th element of the array to the value of CAPSLOCK which presumably is defined in the code above the code you're showing.
The version in your code without the = seems to be a gcc specific extension.
I was examining some code on github https://github.com/umlaeute/v4l2loopback/blob/master/v4l2loopback.c and came across this line, which baffles me. Is this some incredibly cool kernel macro or gcc feature that I don't know about? What does the = -1 do?
static int video_nr[MAX_DEVICES] = { [0 ... (MAX_DEVICES-1)] = -1 };
module_param_array(video_nr, int, NULL, 0444);
MODULE_PARM_DESC(video_nr, "video device numbers (-1=auto, 0=/dev/video0, etc.)");
The line in question is the first, the next two given for context (this is creating a cmdline-specifiable parameter using a kernel macro http://lxr.free-electrons.com/source/include/linux/moduleparam.h#L103 )
Anyway, what is going on with the array initialization? How does that syntax work?
You've found an example of designated initializers. C99 & C11 don't go quite as far as your example, but they have some pretty flexible support for this kind of behaviour. Your specific example (using the ...) is a GCC extension. From the link:
To initialize a range of elements to the same value, write [first ... last] = value. This is a GNU extension. For example,
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
So that means your example is creating an array of size MAX_DEVICES and initializing every element in that array to -1.
For reference, the only standard-supported behaviour is to assign specific indices, rather than ranges:
[constant-expression] = initializer-value
There is a more complicated example in my copy of the spec:
int a[MAX] = {
1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0
};
Which initializes the first five and last five elements of the array to explicit values. The middle values (if any) would be 0.
static uint8_t togglecode[256] = {
[0x3A] CAPSLOCK,
[0x45] NUMLOCK,
[0x46] SCROLLLOCK
};
What's the meaning of [0x3A] here? I have only learned statements like int a[2] = {1, 2};
It means initialise the n-th element of the array. The example you've given will mean that:
togglecode[0x3A] == CAPSLOCK
togglecode[0x45] == NUMLOCK
togglecode[0x46] == SCROLLLOCK
These are called "designated initializers", and are actually part of the C99 standard. However, the syntax without the = is not. From that page:
An alternative syntax for this which has been obsolete since GCC 2.5 but GCC still accepts is to write [index] before the element value, with no =.
According to the GCC docs this is ISO C99 compliant. They refer to it as "Designated Initializers":
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 };
I've never seen this syntax before, but I just compiled it with gcc 4.4.5, with -Wall. It compiled successfully and gave no warnings.
As you can see from that example, it allows you to initialize specific array elements, with the others being set to their default value (0).
That was introduced in C99 and it's called a designated initialiser.
It basically allows you to set specific values in an array with the rest left as defaults.
In this particular case, the array indexes are the keyboard scan codes. 0x3a is the scan code in set #1 (see section 10.6) for the CapsLock key, 0x45 is NumLock and 0x46 is ScrollLock.
On the first link above, it states that:
int a[6] = { [4] = 29, [2] = 15 };
is equivalent to:
int a[6] = { 0, 0, 15, 0, 29, 0 };
Interestingly enough, though the link states that = is necessary, that doesn't appear to be the case here. That's not part of the standard but is a hangover from a rather old version of gcc.
It's (close to) the syntax of designated initializers, a C99 feature.
Basically, it initializes parts of an array, for example;
int aa[4] = { [2] = 3, [1] = 6 };
Intializes the second value of the array to 6, and the third to 3.
In your case the array offsets happen to be in hex (0x3a) which initializes the 58'th element of the array to the value of CAPSLOCK which presumably is defined in the code above the code you're showing.
The version in your code without the = seems to be a gcc specific extension.