一. 将语句跟声明放在表达式里面
({ 语句、 声明 }) ,可以任意组合声明和语句,但是最后必须是一个语句,表示整个表达式的返回值
比如:
二. 局部标签
__label__ end;
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 3; ++j)
if (i + j > 8)
goto end;
end:
三. 嵌套函数 (限C代码)
void f()
{
void g()
{
}
}
四. typeof
typeof可以简化代码的书写。
五. 省略操作数的三元表达式
z = x ? : y “等价于” z = x ? x : y
当x具有副作用(比如x++)时,后者的结果可能不是你期望的;如果x是一个复杂的表达式,前者可以不用重复运算。
六. 零长数组
虽然声明为0长,但是使用时body的下标可以大于0,只要指向合法的内存区域即可。
七. 变成数组
int size = 0;
scanf(“%d”, &size);
int array[size];
这里的变长不是指数组大小可以改变,而是说数组大小可以在使用时指定,而不是编译时指定。
八. 给变长参数命名
#define debug(format, args...) fprintf (stderr, format, ##args)
这里的变长参数命名为args。
不命名的版本是: #define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
九.非常量初始化
非扩展版本初始化只能类似这样:int array[] = { 3, 4 };
十.按指定位置赋值(限C代码)
int a[6] = { [4] = 29, [2] = 15 };
等价于
int a[6] = { 0, 0, 15, 0, 29, 0 };
还可以指定区间
int a[101] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
可以对某些值赋值多次,如:
甚至可以连续赋值:
int a[6] = { [1] = 3, 2, [5] = 8} ó int a[6] = {0, 3, 2, 0, 0, 8}
int a[6] = {} ó int a[6] = {0}, 全部赋值为0
struct S
{
int a;
long b;
};
S s = { .b = 3, .a = 4;} ó S s = {b: 3, a: 4} ó S s = {4, 3}
十一. switch case range
switch (x)
{
case 1000 … 2000 :
…..
case ‘a’ … ‘z’:
…
}
十二. 向union类型转换
union MyUnion { int i; double d; };
int x;
double y;
MyUnion mu = (MyUnion)x; ó MyUnion mu; mu.i = x;
MyUnion mu = (MyUnion)y; ó MyUnion mu; mu.d = y;
十三. 函数属性
1) always_inline属性
inline void DoSomething() { … }
当编译不加-Oxx选项时,必不会内联。
强制内联(其实也只是建议而已,看编译器的心情):
inline void __attribute__((always_inline)) DoSomething()
{}
2) constructor & destructor属性
constructor使得函数在main之前执行,destructor属性使得函数在main之后执行。见测试:
3)format属性
format (
checktype,
format-index, first-to-check)
一般来说 first-to-check = format-index + 1
注意图中fmt是第二个参数,但是printf后面却是3!因为类的成员函数第一个参数是隐藏的!实际上fmt是第三个参数。