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,
#ifndef CONFIG_MMU
.mmap_capabilities = zero_mmap_capabilities,
#endif
};
未初始化成员为 0,或者 NULL。
5. 可变参数
#define printk(fmt, ...) printf(fmt, ##__VA_ARGS__)
"..." 代表一个可以变化的参数表,"__VA_ARGS__" 是编译器保留字段,预处理时把参数传递给宏。
6. 函数属性
GNU C 允许声明函数属性,变量属性和类型属性,以便编译器进行特定优化和代码检查。
attribute((attribute-list))
常用的有 noreturn , format const,interrupt,isr 等;
#ifndef __pure
#define __pure __attribute__((pure))
#endif
#define noinline __attribute__((noinline))
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#ifndef __noreturn
#define __noreturn __attribute__((noreturn))
#endif
#ifndef __aligned
#define __aligned(x) __attribute__((aligned(x)))
#endif
#define __printf(a, b) __attribute__((format(printf, a, b)))
#define __scanf(a, b) __attribute__((format(scanf, a, b)))
__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 预取指令的正确性;
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
__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;
防止两个整数相加,结果溢出;