C语言结构体struct详解与实例

目录

1.定义

2.应用

2.1初始化

2.2使用

3.结构体对齐规则与存储


1.定义

C语言中结构体(struct关键字定义)是一种自定义数据类型。通过结构体的定义可以将多种不同类型数据形成一个组合,是一个数据集。

什么情况下使用结构体?结构体的定义具有一定面向对象思想,当一个对象具有多个属性类型数据去表达时,可以定义为结构体,比如学生,结构体成员包含姓名、年龄、学号、成绩。

定义方法如下:

方法一:直接使用struct关键字定义结构体
struct 结构体名称
{
    结构体成员1类型  结构体成员1名称;
    结构体成员2类型  结构体成员2名称;
    ......
    结构体成员N类型  结构体成员N名称;
};//注意结束分号

方法二:使用typedef定义,简化使用
typedef struct 结构体名称
{
    结构体成员1类型  结构体成员1名称;
    结构体成员2类型  结构体成员2名称;
    ......
    结构体成员N类型  结构体成员N名称;
}自定义结构体类型名称;//注意结束分号

定义一个学生类型结构体实例: 

//方法一
struct student_t
{
    char name[20];//姓名
    unsigned char age;//年龄
    unsigned int number;//学号
    float grade;//成绩
};//注意需要有分号结束,组成一个完整语句

//方法二
typedef struct student_t
{
	char name[20];//姓名
	unsigned char age;//年龄
	unsigned int number;//学号
	float grade;//成绩
}Student_t;//注意需要有分号结束,组成一个完整语句

2.应用

2.1初始化

1、方法一:定义时隐性赋值

struct student_t stdu ={ "Tom", 20, 0x9001, 89.5,};

说明: 此方法初始化时不需要写明成员名称,但需按照结构体成员顺序进行赋值,不能错位。

2、方法二:定义时显性赋值

	struct student_t stdu =
	{
		.name = "Tom",
		.age = 20,
		.number = 0x9001,
		.grade = 89.5,
	};

 说明:此方法初始化时显性给出了结构体成员名称,逐个赋值,可以进行乱序赋值(即不按照成员的顺序进行赋值),但为了保持良好编程风格,建议按顺序进行赋值。

3、方法三:先定义再赋值

struct student_t stdu;
//stdu.name = "Tom";//注意:不能直接对数组名赋值字符串常量,此处了解数组和指针相关知识
strcpy(stdu.name, "Tom");
stdu.age=20;
stdu.number=0x9001;
stdu.grade=89.5;

说明:此方法和方法二一样,可以不按顺序赋值。类似一般类型变量定义之后,再赋值。 

2.2使用

以学生结构体定义后打印到控制台为例,以下是在VS2022中调试可运行的完整C代码

#include 
#include 
#include 
#include 
#include 

#pragma warning(disable:4996)//用以解决strcpy不安全使用编译错误问题

typedef struct student_t
{
	char name[20];//姓名
	unsigned char age;//年龄
	unsigned int number;//学号
	float grade;//成绩
}Student_t;//注意需要有分号结束,组成一个完整语句

int main(int argc, char* argv[])
{
	//方法一
	//Student_t stdu ={ "Tom", 20, 0x9001, 89.5,};
	// 
	//方法二
	Student_t stdu =
	{
		.name="Tom",//注意此处不能使用stdu.name,因为是不可修改左值
		.age=20,
		.number=0x9001,
		.grade=89.5,
	};
	// 
	// 
	//方法三
	//struct student_t stdu;
	stdu.name = "Tom";//不能直接对数组名赋值字符串常量,此处了解数组和指针相关知识
	//strcpy(stdu.name, "Tom");
	//stdu.age = 20;
	//stdu.number = 0x9001;
	//stdu.grade = 89.5;

	printf("Student information:\n");
	printf("	name: %s\n", stdu.name);
	printf("	age: %d\n", stdu.age);
	printf("	number: %x\n", stdu.number);
	printf("	grade: %f\n", stdu.grade);

	return 0;
}

运行后效果截图:

 C语言结构体struct详解与实例_第1张图片

3.结构体对齐规则与存储

结构体在内存中存储需符合以下2条规则:

1. 结构体每一个成员的偏移量都必须是该成员存储大小的倍数。

2. 完整结构体的大小必须是该结构体字节数最大成员类型的倍数。(注意是类型大小而不是成员变量大小)。

以学生结构体(struct student_t)为例说明:

第一个成员name偏移量是0,符合规则一;

第二个成员age偏移量是20,是char类型整数倍,符合规则一;

第三个成员number偏移量是name变量大小加age变量大小,即20+1=21,而unsigned int类型长度是4,21不是4的整数倍,不符合规则一。需要进行大小补齐,补齐到24后符合规则一;

第四个成员grade偏移量是24(补齐后)+4=28,符合规则一;

整个结构体大小是grade成员偏移量加grade变量自身大小,即28+4=32字节。

验证规则二:成员中字节数最大类型是float,4字节(unsigned int也是4字节),32是4字节的倍数,无需补齐,所以整个学生结构体大小就是32。

注:规则二说明的是类型而不是成员变量,成员变量name的大小是20字节,但其类型是char,1字节,4个成员变量类型分别是char、unsigned char、unsigned int、float,所以最大字节数的类型是unsigned int和float,是4字节。

存储图示如下:

C语言结构体struct详解与实例_第2张图片

 

使用sizeof计算,运行输出大小如下

你可能感兴趣的:(C/C++,c语言,c++,开发语言)