C语言:结构体

本文详细介绍了C语言中结构体的定义、创建、初始化过程,包括结构体成员的两种调用方式,以及如何使用typedef简化代码。此外,还探讨了结构体内存大小的计算和内存对齐规则。
摘要由CSDN通过智能技术生成

目录

前言

一、结构体的概念

二、结构体的创建

三、结构体的初始化

四、结构体成员的调用

1.对结构体变量调用成员调用    

2.对结构体的地址调用成员变量

三、在结构体中利用 typedef 来简化代码

1.基本的使用方法

2.使用方法扩展 (匿名结构体)

四、结构体的内存大小

结尾


前言

        在c语言中,不仅有整型浮点型等c语言自带的类型,还有结构体,枚举等自定义类型。在这篇文章中就来讲讲结构体类型。

一、结构体的概念

        在现实生活中,我们往往有各种各样的整体,像学生,书籍,水杯等等,这些整体都有它们各自的信息,就比如学生,就有学号,性别,姓名等等。那么在编程中,我们要怎样来创造这种整体呢?c语言就给我们提供了结构体这种自定义类型,这种类型就可以包含其他的各种类型,乃至于结构体类型。这样我们就可以用一个类型来表示一个整体了。

二、结构体的创建

        

        结构体的创建就是像上面的代码这样,struct S, 表示创建了一个结构体变量叫 struct Stu,内部的 name , number, age, sex 都是 struct Stu 的成员变量, 写哪些类型的成员变量主要看我们的需要。成员变量无需初始化赋值,也就是写出类型与变量名就行了。别忘记了每个成员变量后面和结构体结尾处的分号

三、结构体的初始化

        下面就是对结构体初始化的代码了

#include<stdio.h>
struct S
{
	int a;
	char arr[5];
	int* p;
};
int main()
{
	struct S s1 = { 5, "hehe", NULL };//初始化时,可以按照结构体中成员变量的顺序来初始化内容
	struct S s2 = { .p = NULL, .arr = "hehe", .a = 45 };//可也以用结构成员访问操作符来随意顺序的初始化内容

	printf("%d %s %p", s1.a, s1.arr, s1.p);

	return 0;
}

        对于结构体来说,它的初始化赋值和数组的差不多,可以用逗号来分隔,依次对成员变量赋值。特别的一点是,对于相同类型的结构体变量,是可以直接使用 = 来把一个结构体变量赋值给另一个结构体变量的。这和数组完全不同。

四、结构体成员的调用

结构体的成员调用有两种方法:

1.对结构体变量调用成员调用    
#include<stdio.h>
struct S
{
	int a;
	char arr[5];
	int* p;
};
int main()
{
	struct S s1 = { 5, "hehe", NULL };
    struct S* p = &s1;

	printf("%d %s %p\n", s1.a, s1.arr, s1.p);
    printf("%d %s %p\n", p->a, p->arr, p->p);

	return 0;
}

       对于结构体变量,可以使用符号 . 来通过结构体变量来调用成员变量。

2.对结构体的地址调用成员变量

        在上面的代码中,结构体类型指针 p ,存放的就是 s1 的地址,可以通过符号 -> 来,借助地址来调用结构体变量中的成员变量。

三、在结构体中利用 typedef 来简化代码

        平时,在定义了结构体类型后,要使用该类型,都要写上 struct ,这样就有些麻烦了,我们就可以通过重命名来方便我们的代码书写。

1.基本的使用方法
#include<stdio.h>

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

} Stu;//即把类型名由 struct Stu 改为了 Stu 方便了之后代码的编写

int main()
{
	Stu s1 = { 0 };//定义了一个结构体变量

	return 0;
}

        在上面的代码中,就是利用了 typedef 简化了代码。 typedef 的使用方法就是给一个类型创建一个新的名字,原来的名字也是可以使用的。格式是:typedef  原来类型  新名字;

需要注意的是别忘了末尾的分号 

2.使用方法扩展 (匿名结构体)

         对于结构体其实还可以不给原来的结构体写名字,直接重新定义名字,什么意思呢?请看下面的代码:

struct
{
	char c;
	int i;
	double d;
} s = {'x', 100, 3.14};//匿名结构体想要经常被使用比较麻烦(没有这个结构体的名字,如何使用?),并且匿名结构体是做不到自引用的
typedef struct
{
	char name[10];
	int age;
} stu;//还可以给匿名结构体重新命名,这样就可以直接使用它的新名字,也不存在多次使用麻烦的问题了

        上面的这两个结构体就没有名字,它们就是匿名结构体 ,要使用匿名结构体就比较麻烦,因为没有具体的名字,我们只能在创建结构体的时候一起创建全局变量,来对它进行使用。而结合上我们的 typedef 就不一样了,不仅可以对结构体重新命名,还可以在之前减少了创建名字的代码。可能看起来很鸡肋,但可以当作知识的扩展,而且看起来不是高级一点吗?

需要注意的一点是,结构体调用自己本身是是无法使用到 typedef 的重新命名的。

像这里,重命名是发生在成员变量创建之后的,所以还得用原先的名字。

四、结构体的内存大小

        结构体占据的内存空间大小,与我们想像的各个结构体成员变量的空间字节数相加是不同的。它会有内存对齐现象,请看下面的代码。

//代码在vs2022下运行
#include<stdio.h>
struct S
{
	char c1;  // 1
	int i;  // 4
	char c2;  // 1
};
struct S1
{
	char c1;  // 1
	char c2;  // 1
	int i;// 4
};
struct S2
{
 char c1;
 struct S s3;
 double d;
};
int main()
{
	struct S s = { 0 };
	
	printf("sizeof(S) = %zd\n", sizeof(struct S));  // 12 结果并不是6,而是12,这是为什么呢?就是发生了结构体的内存对齐
	printf("sizeof(S1) = %zd\n", sizeof(struct S1));  // 8 可见,即便结构体成员的类型都相同,不同的先后顺序也会有内存大小的偏差(所以把小内存的成员集中在一起可以减小内存的占用)
	printf("sizeof(S2) = %zd\n", sizeof(struct S2));  // 24


	return 0;
}

摘抄:

结构体体对齐规则:

1. 结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
        对齐数 = 编译器默认的⼀个对齐数 与 该成员变量大小的较小值。
        - VS 中默认的值为 8
        - Linux中 gcc 没有默认对齐数,对⻬数就是成员自身的大小
3. 结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

        这里就讲解一下上面的代码,结构体 S 的空间占据情况如图:

        这里,char 类型的 c1 要占一个字节的空间,按照规则 1,占据了空间 0,然后 int 类型 i ,对齐数是 4 ,( 4 < 8 取4),按照规则2,要从 4 的整数倍位置开始占空间,然后是 c2,对齐数是 1,所以占到空间 8 ,到目前为止占据空间为 9 个空间,按照规则3,占据的空间要是成员变量中最大的对齐数(也就是 i 的对齐数 4)的整数倍,所以要占据12个空间。

        同理,与结构 S 体成员变量相同,但是顺序不同 s1 ,占据的空间如下,只有8个位置。

        最后的结构体 s2,就让各位看官自己来思考一下。我就不多讲了😁

结尾

        到这里,结构体的一下相关知识就讲到这里了,别忘了点赞收藏加关注(●'◡'●)

  • 38
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值