结构体、结构体大小的计算

结构体

数组是存储相同数据类型变量的集合,但是无法存储不同数据类型的变量。

比如,存放学生的名字+年龄+性别+学号 这几项信息,就无法实现。

那么C语言为了解决这个问题就有了结构体的概念。

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。

结构体的定义

struct tag
{
 	member-list;
    ...
}variable-list;

struct:struct是关键字,定义结构体,必须使用 struct 语句

tag:结构体的标识符

member-list:结构体的成员变量

variable-list:结构体变量,您可以指定一个或多个结构体变量,这是一个全局变量(可以不写,不写的话这里就是声明结构体)

代码示例

struct Stu {
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}; //分号不能丢
//上面只是声明结构体

struct Books
{
	char  title[50];//标题
	char  author[50];//作者
	char  subject[100];//主题
	int   book_id;//编号
} book;//声明类型的同时定义变量book,这里是全局变量

int main()
{
	//定义struct Stu类型变量
	struct Stu stu;

	//定义struct Books类型变量
	struct Books book1;
	return 0;
}

特殊的结构体定义

在声明结构的时候,可以不完全的声明。

//此结构体没有标识符,是一个匿名结构体
struct
{
	int a;
	char b;
	double c;
}s1;//声明类型的同时定义变量s1

struct
{
	int a;
	char b;
	double c;
} *p1;//声明类型的同时定义变量*p1

//使用typedef创建新类型,my_struct代表struct s2这个类型
typedef struct s2
{
	int a;
	char b;
	double c;
} my_struct;

//结构体嵌套
struct Point
{
	int x;
	int y;
};

struct Node
{
	int data;
	struct Point p;//结构体的成员变量是结构体
	struct Node* next;
};

int main()
{
	//这两个匿名结构体虽然成员变量一样,但是编译器会把它们看成是不同的类型
	*p1 = &s1; //错误

	//定义使用typedef创建的新类型my_struct
	my_struct s3;

	return 0;
}

结构体的初始化

和其它类型变量一样,对结构体变量可以在定义时指定初始值。

struct Books
{
	char  title[50];
	char  author[50];
	char  subject[100];
	int   book_id;
} book = { "C 语言", "Aping", "编程语言", 123456 };

struct Stu {
	char name[20];
	int age;
	char sex[5];
	char id[20];
};
struct Stu stu1 = { "张三",18,"男","10086" };

//匿名结构体
struct
{
	int a;
	char b;
	double c;
}s1;

s1 = { 8,'a',3.14 };

//结构体嵌套
struct Point
{
	int x;
	int y;
};

struct Node
{
	int data;
	struct Point p;
	struct Node* next;
};

struct Node node1 = { 88,{6,9},NULL };

访问结构体成员变量

我们可以使用**成员访问运算符(.)**访问结构的成员变量

也可以使用->符号通过结构体的指针访问结构的成员变量

代码示例

struct Stu {
	char name[20];
	int age;
	char sex[5];
	char id[20];
};

int main()
{
	struct Stu stu1 ;
	strcpy(stu1.name, "张三");
	stu1.age = 18;
	strcpy(stu1.sex, "男");
	strcpy(stu1.id, "123456");

	//使用成员访问运算符(.)访问结构的成员变量
	printf("%s\n", stu1.name);
	printf("%d\n", stu1.age);
	printf("%s\n", stu1.sex);
	printf("%s\n", stu1.id);

	//使用->符号通过结构体的指针访问结构的成员变量
	struct Stu* ps = &stu1;
	printf("%s\n", ps->name);
	printf("%d\n", ps->age);
	printf("%s\n", ps->sex);
	printf("%s\n", ps->id);
	return 0;
}

结构体作为参数传参

struct Stu {
	char name[20];
	int age;
	char sex[5];
	char id[20];
};

void Stu_printf(struct Stu stu)
{
	printf("%s\n", stu.name);
	printf("%d\n", stu.age);
	printf("%s\n", stu.sex);
	printf("%s\n", stu.id);
}

void Stu_printf_p(struct Stu* ps)
{
	printf("%s\n", ps->name);
	printf("%d\n", ps->age);
	printf("%s\n", ps->sex);
	printf("%s\n", ps->id);
}

int main()
{
	struct Stu stu1;
	strcpy(stu1.name, "张三");
	stu1.age = 18;
	strcpy(stu1.sex, "男");
	strcpy(stu1.id, "123456");

	//结构体作为参数传参
	Stu_printf(stu1);

	//结构体指针作为参数传参
	struct Stu* ps = &stu1;
	Stu_printf_p(ps);

	return 0;
}

结构体内存对齐(计算结构体大小)

结构体的对齐规则:

  1. 第一个成员在与结构体变量偏移量为0的地址处。

  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

    对齐数:编译器默认的一个对齐数与该成员类型大小的较小值。(VS中默认的值为8)

  3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

代码示例1

struct S1
{
	char c1;
	int i;
	char c2;
	double d;
};

int main()
{
	printf("%d\n", sizeof(struct S1));// 24
	return 0;
}

代码示例2

struct S2
{
	char c1;
	char c2;
	int i;
	double d;
};

int main()
{
	printf("%d\n", sizeof(struct S2));//16
	return 0;
}
注:

我们发现共用体S1和S2的成员变量是一样的,但是所占的空间不一样

造成这样的问题是因为S1和S2的成员变量的位置不一样

所以为了节省空间,我们要让占用空间小的成员尽量集中放在一起

代码示例3

struct S2
{
	char c1;
	char c2;
	int i;
	double d;
};

//结构体嵌套问题
struct S3
{
	char c1;
	struct S2 s2;
	double d;
};

int main()
{
	printf("%d\n", sizeof(struct S3));// 32
	return 0;
}

本文出现任何错误,欢迎留言批评指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值