__attribute__((packed))

最近在写结构体的时候经常遇到下面的这种代码

1
2
3
4
5
// GDTR
typedef struct {
uint16_t limit; // 全局段描述符限长 0 ~ 15
uint32_t base; // 全局段描述符表32位基地址 16 ~ 47
} __attribute__((packed)) gdt_ptr_t;

__attribute__关键字主要是用来设置函数属性(Function Attribute)、变量属性(Variable Attribute)、类型属性(Type Attribute)。也可以修饰结构体(struct)或共用体(union)。设置属性的主要目的在于让编译器进行优化。

写法为__attribute__ ((attribute-list)),后面的 attribute-list 大概有6个参数值可以设置:aligned, packed, transparent_union, unused, deprecatedmay_alias。(详情请参见GCC文档)

packed 的作用就是告诉编译器:取消结构体在编译过程中的优化对齐,按照实际占用字节数进行对齐,是GCC特有的语法。

参考编译器特性 attribute_((packed))

函数指针

函数指针的形式1: 返回类型(*函数名)(参数1的类型, 参数2的类型, ...)

1
2
3
4
5
6
7
8
9
10
11
12
13
void (*test)(int);  // 定义一个函数指针test,它指向一个返回类型为void,形参为int的类型的函数

void neg(int a){
printf("%d", a);
}

int main(){

test = neg;
(*test)(3); // 等同于 test(3);

return 0;
}

(*test)(3);test(3); 的运行结果一样。ANSIC规定了test(3)(*test)(3)的简写。其实函数名本质上也是一个地址, 有点类似于数组名其实也是地址。

typedef 可以让函数指针更直观方便。

函数指针的形式2: typedef 返回类型(*新类型)(参数1的类型, 参数2的类型, ...)

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef void (*TEST)(int);

void neg(int a){
printf("%d", a);
}

int main(){
TEST test;
test = neg;
test(3);

return 0;
}

typedef void (*Fun) (void) 的理解

(未完待续)