结构体

本文详细介绍了结构体的定义、声明及如何作为函数参数使用。重点讨论了结构体中成员的偏移量计算规则和结构体大小的确定,包括字节对齐的原则,以及编译器如何在成员之间插入填充字节以满足对齐要求。通过一个具体的例子,解释了为什么实际结构体大小可能与成员大小简单相加不同。

定义与声明

结构体的定义如下所示,struct为结构体关键字,tag为结构体的标志,member-list为结构体成员列表,其必须列出其所有成员;variable-list为此结构体声明的变量。 

 

 struct tag 

{

   member-list

 } variable-list ;




访问结构的成员//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct 
{
    int a;
    char b;
    double c;
} s1;
 
//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE
{
    int a;
    char b;
    double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;
 
//也可以用typedef创建新类型
typedef struct
{
    int a;
    char b;
    double c; 
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;
struct SIMPLE t1, t2[20], *t3;
 
//也可以用typedef创建新类型
typedef struct
{
    int a;
    char b;
    double c; 
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;

为了访问结构的成员,我们使用成员访问运算符(.)。成员访问运算符是结构变量名称和我们要访问的结构成员之间的一个句号。您可以使用 struct 关键字来定义结构类型的变量。下面的实例演示了结构的用法

#include<stdio.h>
#include<windows.h>

#pragma warning(disable:4996)
#define NUM 2

struct list
{
	char Name[10];
    char Age[10];
    char Sex[10];
	char Tel[20];
	char Add[20];
};
int main()
{
	int i;
	struct list student[NUM];
	for(i=0;i<NUM;i++)
	{
		printf("please input student name\n");
		scanf("%s",student[i].Name);
		printf("please input student age\n");
		scanf("%d",student[i].Age);
		printf("please input student sex\n");
        scanf("%s",student[i].Sex);
		printf("please input student tel\n");
		scanf("%d",student[i].Tel);
		printf("please input student add\n");
		scanf("%s",student[i].Add);
		printf("\n");
	}
	for(i=0;i<NUM;i++)
	{
		printf("  name %s\n  age %d\n  sex %s\n  tel %d\n add %s\n",student[i].Name,student[i].Age,student[i].Sex,student[i].Tel,student[i].Add);
	}
	system("pause");
}

 

结构作为函数参数

您可以把结构作为函数参数,传参方式与其他类型的变量或指针类似。您可以使用上面实例中的方式来访问结构变量:

void search(struct list student[NUM])
{

}

                                         


                                                 结构体大小计算

定义

结构体中的偏移量

结构体中的偏移量是一个成员的实际地址和结构体首地址之间的距离。

结构体大小计算

结构体大小 会涉及到字节对齐(目的是 让计算机快速读写 以空间换取时间)。即,最后一个成员的偏移量加上最后一个成员的大小再加上末尾的填充字节数。

结构体内偏移规则

1、每个成员的偏移量都必须是当前成员所占内存大小的整数倍如果不是编译器会在成员之间加上填充字节。 
2、当所有成员大小计算完毕后,编译器判断当前结构体大小是否是结构体中最宽的成员变量大小的整数倍 如果不是会在最后一个成员后做字节填充。

struct unknown {
    int a;
    char b;
    int c;
    long d;
    char e;
};
printf("%lu\n", sizeof(struct unknown));
//output : 32

结构体重共有一个long类型,两个char类型,两个int类型成员。如果只按照这几个成员大小相加,结构体大小应该是 8 + 2 * 4 + 2 * 1 = 18 个字节大小。但实际上该结构体是32个字节大小。

下面来一步步分析编译器是如何计算大小进行分配的。(以下未标明单位的数字以字节为单位)

1、遇到第一个成员变量a,该成员偏移量为0,大小为4,符合偏移规则第一条。 
2、接下来第二个成员变量b,偏移量为4,大小为1,符合偏移规则第一条。 
3、成员变量c,偏移量为5,大小为4,不符合偏移规则第一条。在成员b和c之间填充三个字节,此时,偏移量大小为8,符合偏移规则第一条,继续往下。 
4、成员变量d,偏移量为12,大小为8,不符合偏移规则第一条,在成员c和d之间填充4个字节,此时偏移量为16,符合偏移规则第一条,继续往下。 
5、成员变量e,偏移量为24,大小为1,符合偏移规则第一条。 
6、所有成员大小计算完后,执行偏移规则第二条,最宽的类型是d,long类型,8个字节,当前结构体计算出的大小为25,并不符合第二条规则,于是在末尾填充7个字节,总大小为32个字节,满足第二条偏移规则。到此结构体大小计算结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值