BeginMan blog

C结构体的种种

一. 结构体变量定义的三种方法

方式1(推荐):用typedef为已存在的结构体类型定义新名字,然后用新名字定义变量名

typedef struct student {
    int num;
    // ...
} STUD;

STUD student1, student2;

方式2:struct VarName完整的写出结构体的类型定义并声明变量

struct student {
    int num;
    // ...
} student1, student2;

struct student student3;

方式3:不定义类型,只定义变量

struct {
    int num;
    // ...
} student1, student2;
// 不能再定义student3了

二. 内存对其

如下一个结构体来看下sizeof打印。

struct {
    char c;
    int i;
} s;

int main()
{
    s.c = 'a';
    s.i = 0x0a0b0c0d;
    printf("%lu\n", sizeof(s)); 
    return 0;
}

运行下打印的是8。来gdb调试看下。

(gdb) p s
$7 = {c = 97 'a', i = 168496141}
(gdb) p &s
$8 = (struct {...} *) 0x100001018 <s>
(gdb) p &(s.c)
$9 = 0x100001018 <s> "a"
(gdb) p &(s.i)
$10 = (int *) 0x10000101c <s+4>

(gdb) x/16b &s
0x100001018 <s>:    97  0   0   0   13  12  11  10
(gdb) x/16b &s->c
0x100001018 <s>:    97  0   0   0   13  12  11  10
(gdb) x/16b &s->i
0x10000101c <s+4>:  13  12  11  10  0   0   0   0

i 变量被对齐到一个4 倍整数的地址上,在内存上,它并不是紧挨着变量c。这种现象叫做内存对齐,对齐以后的地址通常都是2 或4 的倍数。这种对齐最终会造成结构体s 内部char 和int 之间有一个“空洞(hole)”。

这种对齐的目的是使处理器能够更快速地进行寻址,以便执行的速度更快。这是一种以空间换时间的策略,虽然有点浪费空间,但是这样查找起来很快。