There is a lot of code in the Linux kernel that uses many of the extended features of GCC, and this article focuses on a small summary of these features, all from the GCC Handbook
1. A block of code that is enclosed by a pair of curly braces can be used as an expression, using a looping statement (while, a for), a switch statement (if, switch), a local variable, and so on. The code is as follows:
| 1234 |
({ inty = foo (); int z; if (y > 0) z = y; elsez = - y; z; }) |
The last statement must be an expression and end with a semicolon, which is used for the return value of the code block in other statements or expressions
| 12 |
#define maxint(a,b) \({int_a = (a), _b = (b); _a > _b ? _a : _b; }) |
This macro definition is much more secure than the following code.
| 1 |
#define max(a,b) ((a) > (b) ? (a) : (b)) |
2. Affirm local label (locally label)
GCC allows the declaration of any local tag in a block of code, but only in the declared code block, as follows
| 1 |
__label__ label1, label2, /* . . . */; |
This statement only declares two label names, but does not define the label itself, but also need to use the label signature followed by a colon (label:) to define the tag, the local label is generally used in a complex macro definition is more effective, if a macro definition in a function is expanded more than once (by multiple references), Then a common label will be duplicated, and the local tag will be good to avoid the problem, such as the following code:
| 123456789101112131415 |
#define SEARCH(array, target) \({ \ __label__ found; \ typeof (target) _SEARCH_target = (target); \ typeof (*(array)) *_SEARCH_array = (array); \ int i, j; \ int value; \ for (i = 0; i < max; i++) \ for (j = 0; j < max; j++) \ if (_SEARCH_array[i][j] == _SEARCH_target) \ { value = i; goto found; } \ value = -1; \ found: \ value; \}) |
3. Get the value of a label
You can get the value of a label (address), the label's worth type is void *, the worthwhile type is a constant, can be used in any place where the type needs to be changed, using the following syntax:
| 1234 |
void*ptr;/* . . . */ptr = &&foo;//foo为一个标签goto*ptr; |
You can also use this:
| 123 |
staticconst int array[] = { &&foo - &&foo, &&bar - &&foo, &&hack - &&foo };goto*(&&foo + array[i]); |
4. Inline functions
The inline function can access any visible variable where it is defined, and for the moment we call the function containing the inline function as containing_function, if we have access to the local variable of containing_function in the inline function, It is very likely that we call inline functions outside the containing_function to cause confusion and the consequences are expected. Conversely, it is safe to call this inline function internally in containing_function, the sample code is as follows:
| 123456 |
hack ( int *array, int size) { &NBSP;&NBSP;&NBSP;&NBSP; void store ( int index, int value) &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP; {array[index] = value;} &NBSP;&NBSP;&NBSP;&NBSP; intermediate (store, size); } |
You can also use tags defined in containing_function in inline functions:
| 1234567891011121314151617181920 |
bar (int *array, int offset, int size){ __label__ failure; int access (int *array, int index) { if (index > size) goto failure; return array[index + offset]; } int i; /* . . . */ for (i = 0; i < size; i++) /* . . . */ access (array, i) /* . . . */ /* . . . */ return 0; /* Control comes here from access if it detects an error. */ failure: return -1;} |
5. Constructors
There are many built-in functions in the GCC compiler these functions have been __buildin_ started and are not described in detail.
6.typeof
If we need a type, we can use TypeOf, which returns the type of a variable. If you want your program to be compatible with iOS C programs, then you can use __typeof__, the sample code is as follows:
| 1234 |
#define max(a,b) \ ({ typeof (a) _a = (a); \ typeof (b) _b = (b); \ _a > _b ? _a : _b; }) |
More usage is as follows:
| 1234567 |
typeof (*x) y;typeof (*x) y;typeof (typeof (char*)[4]) y;//等同于char *y[4];#define pointer(T) typeof(T *)#define array(T, N) typeof(T [N])array (pointer (char), 4) y; |
__auto_type can be used in GNU C + +
7. Omit the operand in the conditional expression
If the conditional expression (? :) omits the first operand, then if the condition is true then the value of the expression is both the value of the condition, as follows:
| 1 |
x ? : y//如果x不为0,那么该表达式的值为x |
8.0 Long arrays
0 long arrays are useful in the last member of a struct, as follows:
| 1234567 |
structf1 { int x; int y[];} f1 = { 1, { 2, 3, 4 } }; struct f2 { struct f1 f1; intdata[3];} f2 = { { 1 }, { 2, 3, 4 } }; |
| 123456 |
struct foo { int X; int y[]; struct bar { struct foo Z;}; struct foo a = {1, {2, 3, 4}}; //Legal struct bar B = {{1, {2, 3, 4}}}; //illegal struct bar C = {{1, {}}}; //Legal struct foo d[1] = {{1, {2, 3, 4}}; //illegal |
9. Non-fixed initialization
The set initialization of automatic variables does not require constant expressions:
| 12345 |
foo (floatf, float g){ floatbeat_freqs[2] = { f-g, f+g }; /* . . . */} |
10. Compound Text Amount
| 12 |
structfoo {int a; char b[2];} structure;structure = ((structfoo) {x + y, ’a’, 0}); |
The above code is equivalent to:
| 1234 |
{ structfoo temp = {x + y, ’a’, 0}; structure = temp;} |
Again for example:
char
**foo = (
char
*[]) {
" x "
};
| 123 |
staticstruct foo x = (struct foo) {1, ’a’, ’b’};static int y[] = (int []) {1, 2, 3};static int z[] = (int[3]) {1}; |
The above code is equivalent to:
| 123 |
staticstruct foo x = {1, ’a’, ’b’};static int y[] = {1, 2, 3};static intz[] = {1, 0, 0}; |
11. Specify initialization
This feature is a frequently used feature:
| 1 |
inta[6] = { [4] = 29, [2] = 15 }; |
Equivalent to:
| 1 |
inta[6] = { 0, 0, 15, 0, 29, 0 }; |
Specify the scope and member designation of the struct:
| 1 |
intwidths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 }; |
| 12345678 |
structpoint { int x, y; };struct point p = { .y = yvalue, .x = xvalue };struct point p = { y: yvalue, x: xvalue }; union foo { int i; double d; };union foo f = { .d = 4 }; structpoint ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 }; |
To be Continued ...
From for notes (Wiz)
A summary of GCC extensions to C