齐量,以字节为单位,例如:
++++ include/asm-i386/processor.h
294: struct i387_fxsave_struct {
295: unsigned short cwd;
296: unsigned short swd;
297: unsigned short twd;
298: unsigned short fop;
299: long fip;
300: long fcs;
301: long foo;
......
308: } __attribute__ ((aligned (16)));
表示该结构类型的变量以 16 字节对齐。通常编译器会选择合适的对齐量,显示指
定对齐通常是由于体系限制、优化等原因。
* packed
属性 packed 用于变量和类型,用于变量或结构域时表示使用最小可能的对齐,用
于枚举、结构或联合类型时表示该类型使用最小的内存。例如:
++++ include/asm-i386/desc.h
51: struct Xgt_desc_struct {
52: unsigned short size;
53: unsigned long address __attribute__((packed));
54: };
域 address 将紧接着 size 分配。属性 packed 的用途大多是定义硬件相关的结
构,使元素之间没有因对齐而造成的空洞。
当前函数名
==========
GNU CC 预定义了两个标志符保存当前函数的名字,__FUNCTION__ 保存函数在源码
中的名字,__PRETTY_FUNCTION__ 保存带语言特色的名字。在 C 函数中,这两个
名字是相同的,在 C++ 函数中,__PRETTY_FUNCTION__ 包括函数返回类型等额外
信息,Linux 内核只使用了 __FUNCTION__。
++++ fs/ext2/super.c
98: void ext2_update_dynamic_rev(struct super_block *sb)
99: {
100: struct ext2_super_block *es = EXT2_SB(sb)->s_es;
101:
102: if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV)
103: return;
104:
105: ext2_warning(sb, __FUNCTION__,
106: "updating to rev %d because of new feature flag, "
107: "running e2fsck is recommended",
108: EXT2_DYNAMIC_REV);
这里 __FUNCTION__ 将被替换为字符串 "ext2_update_dynamic_rev"。虽然
__FUNCTION__ 看起来类似于标准 C 中的 __FILE__,但实际上 __FUNCTION__
是被编译器替换的,不象 __FILE__ 被预处理器替换。
内建函数
========
GNU C 提供了大量的内建函数,其中很多是标准 C 库函数的内建版本,例如
memcpy,它们与对应的 C 库函数功能相同,本文不讨论这类函数,其他内建函数
的名字通常以 __builtin 开始。
* __builtin_return_address (LEVEL)
内建函数 __builtin_return_address 返回当前函数或其调用者的返回地址,参数
LEVEL 指定在栈上搜索框架的个数,0 表示当前函数的返回地址,1 表示当前函数
的调用者的返回地址,依此类推。例如:
++++ kernel/sched.c
437: printk(KERN_ERR "schedule_timeout: wrong timeout "
438: "value %lx from %pn", timeout,
439: __builtin_return_address(0));
* __builtin_constant_p(EXP)
内建函数 __builtin_constant_p 用于判断一个值是否为编译时常数,如果参数
EXP 的值是常数,函数返回 1,否则返回 0。例如:
++++ include/asm-i386/bitops.h
249: #define test_bit(nr,addr)
250: (__builtin_constant_p(nr) ?
251: constant_test_bit((nr),(addr)) :
252: variable_test_bit((nr),(addr)))
很多计算或操作在参数为常数时有更优化的实现,在 GNU C 中用上面的方法可以
根据参数是否为常数,只编译常数版本或非常数版本,这样既不失通用性,又能在
参数是常数时编译出最优化的代码。
* __builtin_expect(EXP, C)
内建函数 __builtin_expect 用于为编译器提供分支预测信息,其返回值是整数表
达式 EXP 的值,C 的值必须是编译时常数。例如:
++++ include/linux/compiler.h
13: #define likely(x) __builtin_expect((x),1)
14: #define unlikely(x) __builtin_expect((x),0)
++++ kernel/sched.c
564: if (unlikely(in_interrupt())) {
565: printk("Scheduling in interruptn");
566: BUG();
567: }
这个内建函数的语义是 EXP 的预期值是 C,编译器可以根据这个信息适当地重排
语句块的顺序,使程序在预期的情况下有更高的执行效率。上面的例子表示处于中
断上下文是很少发生的,第 565-566 行的目标码可能会放在较远的位置,以保证
经常执行的目标码更紧凑。
[next]
gcc扩展(extension) GCCe
1.表达式的陈述和申明。
数据安全性
in Standard C:
#define max(a,b) ((a)>(b)?(a):(b))
in Gcc: ( assume type is int )
#define maxint(a,b)
({int _a=(a), _b=(b),;
_a>_b?_a:_b;})
2.本地申明标签(locally declared labels)
in Gcc:
__label__ name ;
3.可附值得标签
" && " 运算符--返回标签地址
in Gcc:
void * ptr;
ptr = &&foo;
goto *ptr;
static void *array[] = { &&foo, &&bar, &&hack };
goto *array;
static const int array[] = { &&foo - &&foo, &&bar -
&&foo, &&hack - &&foo };
goto * (&&foo+ array);
4.陷套函数(nested function)
5.构建函数调用(contructing function call)
in Gcc:
void * __builtin_apply_args()
返回一个由参数指针寄存器,结构值地址(structure value
address),全部寄存器组成的堆栈的地址
void * __builtin_apply( void (*function)(), void * arguments, size_t size)
用 *arguments和size指定的参数调用 (*function).
void * __builtin_return( void * result)
返回result从包含的函数
6.给表达式取名字(naming an expression`s type)
typedef
7.用typeof()递交类型
如果是在 *.h 文件里,则用 __typeof__
8.推广的左附值
in Gcc:
(a , b) += 5
a, (b +=5 )
&(a,b)
a, &b
( a ? b : c ) = 5
( a ? b = 5 : ( c = 5 ))
(int)a = 5
(int) ( a = (char *)(int) 5 )
(int)a += 5
(int) ( a = (char *)((int)a + 5))
*&(int)f = 1
9.条件省略
in Gcc:
x ? : y EQU x ? x : y
10.双字整形数
in Gcc:
long long
unsigned long long
LL
ULL
11.复杂数
in Gcc:
_Complex
__complex__
__imag__
12.16位浮点数
in Gcc:
0x0.f is (15/16)
p3 is multiplies by 8
so
0x0.fp3 is 1.55e1
13.长度为0的矩阵(arrays of length zero)
14.可变长度矩阵(arrays of variable length)
in Gcc:
struct entry
tester (int len, char data[len][len]){
}
15.可变量参数的宏( macros with variable number of arguments)
in Gcc:
#define debug(format, ...) fprintf(stderr, format, __VA_ARGS__)
"..."是一个可变参数
16.slightly looser rules for escaped newlines
17.string literals with embedded newlines
18.non-lvalue arrays may have subscripts
in Gcc:
struct foo{ int a[4]};
struct foo f();
bar (int index){
return f().a[index];
}
19.void- 和 function-pointers 的转换( arithmetic on void- and function-pointer)
arg with gcc:
-Wpointer-arith -- to warning if the arithmetic are used
20.非常数初始化( non-constant initializers )
in Gcc:
foo(float f, float g){
float beat_freqs[2] = { f-g, f+g };
}
21.字面上的组合( compound literals )
22.指明的初始化( designated initializers )
in Gcc:
int a[6] = { [4] = 29, [2] = 15};
int withs[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3};
23. case ranges
24. cast to a union type
25. mixed devlarations and code
26. declaring attributes of functions
in Gcc:
__attribute__
total 14 attributes: noreturn, pure, const, format, format_arg,
no_instrument_function, section, constructor, destructor, unused, weak, malloc, alias,
no_check_memory_usage,regparm(number),stdcall,cdecl,longcall,short_call....
27.属性语法(attribute syntax)
本节描述__attribute__可能用到的语法,和在C中属性特殊绑定的构造,一些细节会多样的对C++?br>蚾bjective C.因为属性文法的不幸,一些在这里描述的格式不能被全部成功地分析。
see 5.26 [function attributes]
5.33 [variable attributes]
5.34 [type attributes]
一个属性指示是格式__attribute__((attribute-list))
一个属性列表可能是一个空的逗号隔开的属性序列,每一个属性是下列中的一个:
1.空
2.字
......
一个属性指示表(attribute specifier list)是一个或多个属性指示,不被任何记号分离
一个属性指示可以出现在标号的冒号后面,除了 case , default
但是它是不用的(unused),但是要用'-Wall'编译
一个属性指示可以是struct, union, enum 指示的一部分,如果struct,union,enum为空则忽略它
另外,一个属性指示可以是一个申明,未名命的计数申明和类型名的一部分
以后,一个属性指示在很多地方作为一个特殊申明符代替了,一些例子在下面
当一个属性指示申明为函数或矩阵的参数,他会付给函数隐含的盖住参数的指针,但是这个现在还没
有真确的实现
任何指示的列表在??????? p172.s4
一个属性指示列表能出现在一个声明前面,而且对他后面的申明都有效
__attribute((noreturn)) void d0(void), __attribute__((format(printf,1,2))) d1(const
char *, ...), d2(void)
其中'noreturn'对全部申明,'format'只能为d1声明,如果为d2声明则产生错误
一个属性指示列表能出现在逗号(,),等号("),分号(")
(****f)(void)
__attribute__((noreturn)),现在'noreturn'属性申明到f,导致警告f不是一个函数,但是以后将
能申明到这个函数 ****f
???
???
??? p173
28.原形和经典风格的函数定义
29.C++风格的注释
30.带美金符号的名字
31.'ESC'常数
ascii ESC = 'e'
32.追根究底的变量和类型对齐
__alignof__(foo)
exp:
__alignof__(double) is 8 on may RISC
__alignof__(double) is 4 or even 2 on more tradidional machine
33.变量的属性
8 attributes:
aligned, mode, nocommon, packed, section, transparent_union, unused, weak,
share(only in WinNT)
NOTE:
mode(mode): byte, __byte__, word, __word__, pointer, __pointer__
nocommon:
用'-fno-common'编译,将会将全部的变量编译为nocommon,直接分配空间给它,并全部置为0,一个?br>淞恐荒茉谝桓鲈次募








