C语言笔记系列之十——结构体

来源:互联网 发布:安装sql之后找不到程序 编辑:程序博客网 时间:2024/05/07 05:00

1.基本格式

struct student

{

  int age;

  char sex;

  float height;

};

struct student s1,s2,s3;

2.结构体成员的引用

变量名.成员名

数组名[下标].成员名

(*指针变量).成员名:点运算符的优先级高于*运算符,所以必须要加括号。

指针变量->成员名

3.同类型的结构体变量之间可以直接赋值

struct student a,b;

b = a;

4.结构体命令的同时定义变量

struct se

{

  int a;

  int b;

}a = {1, 2},b,s[10];

注意:这里的se不是必须的,如果不加se那么后面无法再定义别的此结构体的变量。

在定义结构体的时候可以初始化,如a的初始化所示。初始化也可以写为{{}, {},{}}外花括号为结构体数组整体的初始化,里面的每个花括号表示每一个数据单元的初始化值。

5.使用typedef重命名结构体

typedef struct se

{

  int a;

  int b;

}student;

注意:se不是必须的。这样命名之后student就等同于struct se。

typedef 原类型名 重命名

typedef int Elemp;  Elemp 就等价于int*。

6.结构体中的对齐规则

    结构体一般会按照结构体中的最大的数据类型(比如结构体里面含有了double那就是按8字节对齐,而结构体里面最大的是int类型那么就会按照4字节对齐)的大小来对齐,所以当我们定义了一个结构体之后使用sizeof()测试出来的大小并不是简单的等于各自单元大小之和。下面一步步来讨论这种对齐的规则,首先看第一个例子:

struct st

{

    char i;

    char j;

    char k;

};

    这个结构体的大小使用sizeof测出来的值是3,根据前面的理解方式,按照最大的单元的类型也就是char来对齐的话,3个字节的答案是很容易的出来的。再来看下面的一个例子:

struct st

{

    char i;

    char j;

    int k;

};

    这次测出来的大小为8,这是为什么呢?因为按照上面的理论,这里会按照int类型的大小也就是4个字节(32位机)来对齐,i,j,k三个变量在内存中的排布是先存放i,然后存放j,最后存放k,同时必须注意的一点就是这些地址不一定是连续的!在我的电脑上打印出来的i和j的地址是连续的,然而k的地址和j的地址之间差了两个字节,说明编译器在j和k中间留了两个字节来实现对齐的功能。这样当然也是为了32位机存取数据的方便,所以这三个变量的地址不一定能够满足特定的规律,但是在排布上面肯定是i在j前,j在k前。再来看第三个例子:

struct st

{

    char i;

    int k;

    char j;

};

    这个例子测试出来的大小值为12,这又是为什么呢?根据上面的分析,编译器为了使程序在运行的时候得到较高的效率,会对结构体的存储做出一定的改变,也可以粗略的理解为内存对齐,如果将k存放在一个非4的倍数开始的地址上的话,读取k的值将会是一件非常头疼的事情,因为32位的机器一次一般读取32bits的数据,也就是4个字节,这也就导致了很多硬件在连接的时候就默认每次处理器都是读取的4个字节(当然读取到之后再剔除不要的数据就得到char、short等之类的变量值了),所以如果你非要放在一个非4的倍数的地址的话,那么处理器就只能分两次读取数值然后再来做拼接工作,这样是非常麻烦的。所以编译器选择了简单的办法,反正保证k的起始地址是4的整数倍,i在k之前没有占够4个字节,也对齐为4个字节,k后面的j也是这样的,所以对齐出来就12个字节了。再看第四个例子:

struct st

{

    char i;

    int k[2];

    char j;

};

这个例子的测试输出大小为16,还是说明上面的结论是正确的,是按最大类型对齐的,而不是按最大的单元块(这里最大的一个单元块就是int k[2]大小是8字节)对齐的。

0 0
原创粉丝点击