1.在GNU C语言中,括号里的复合语句可以看作一个表达式;
#define max(a,b) ((a) > (b)?(a):(b)) | |
#define max(a,b) \ | |
({int _a = (a), _b = (b);(_a) > (_b)?(_a):(_b)}) |
2.零长数组
struct line { | |
int length; | |
char data[0]; | |
}; | |
struct line *shisline=malloc(sizeof(struct line) + this_length); | |
thisline->length = this_length; | |
sizeof(struct line) = sizeof(int); |
3.case范围
case可以用一个范围做标签
case 'a'...'z':
4.标号元素
标准C语言要求数组或结构体,必须按固定顺序出现;但GNU C可以通过制定索引或结构体成员名来初始化,不必按固定顺序;
static const struct file_operations zero_fops = { | |
.llseek = zero_lseek, | |
.write = write_zero, | |
.read_iter = read_iter_zero, | |
.read = read_zero, | |
.write_iter = write_iter_zero, | |
.mmap = mmap_zero, | |
.get_unmapped_area = get_unmapped_area_zero, | |
.mmap_capabilities = zero_mmap_capabilities, | |
}; |
未初始化成员为0,或者NULL。
5.可变参数
#define printk(fmt, ...) printf(fmt, ##__VA_ARGS__)
"..."代表一个可以变化的参数表,"__VA_ARGS__"是编译器保留字段,预处理时把参数传递给宏。
6.函数属性
GNU C允许声明函数属性,变量属性和类型属性,以便编译器进行特定优化和代码检查。
attribute((attribute-list))
常用的有noreturn , format const,interrupt,isr等;
__aligned(x):规定变量或结构体成员的最小对齐格式,单位字节;
packed属性使变量或结构体成员使用最小的对齐方式;
struct test | |
{ | |
char a; | |
int x[2] __attribute__((packed)); | |
} | |
sizeof(struct test) = 9bytes; |
7.内建函数
"_builtin" 作为前缀
__builtin_constant_p(x):判断x是否在编译时就可以确定为常量,是则返回1,否则返回0;
__builtin_expect(exp,c):exp==c的概率很大,用来引导GCC编译器进行条件分支预测,优化指令序列,提高CPU预取指令的正确性;
__builtin_prefetch(const void*addr, int rw, int locality):主动进行预取,在使用addr之前,
就把其值加载到cache中,减少读取的延迟,提高性能;
addr:要预取数据的地址;
rw:表示读写属性,1为可写,0表示只读;
locality:表示数据在cache中的时间局部性,其中0表示读取完addr之后不用保留在cache中,而1~3表示时间局部性逐渐增强;
void __free_pages_core(struct page *page, unsigned int order) | |
{ | |
unsigned int nr_pages = 1 << order; | |
struct page *p = page; | |
unsigned int loop; | |
/* | |
* When initializing the memmap, __init_single_page() sets the refcount | |
* of all pages to 1 ("allocated"/"not free"). We have to set the | |
* refcount of all involved pages to 0. | |
*/ | |
prefetchw(p); | |
for (loop = 0; loop < (nr_pages - 1); loop++, p++) { | |
prefetchw(p + 1); | |
__ClearPageReserved(p); | |
set_page_count(p, 0); | |
} | |
__ClearPageReserved(p); | |
set_page_count(p, 0); | |
atomic_long_add(nr_pages, &page_zone(page)->managed_pages); | |
/* | |
* Bypass PCP and place fresh pages right to the tail, primarily | |
* relevant for memory onlining. | |
*/ | |
__free_pages_ok(page, order, FPI_TO_TAIL | FPI_SKIP_KASAN_POISON); | |
} |
8.UL
1:表示有符号整型数字1;
1UL:表示无符号长整型数字1;
防止两个整数相加,结果溢出;