c语言-结构体详解

1.结构体介绍:

结构体(struct)是C、C++、C#等编程语言中的一种复合数据类型,它允许您把多个不同类型的数据项组合成一个单独的类型。通过使用结构体,您可以创建一个自定义的数据类型,该类型包含多个字段,每个字段可以存储不同类型的数据。

在C语言中,结构体的定义通常如下

struct 结构体名 {  
    数据类型 成员变量名1;  
    数据类型 成员变量名2;  
    ...  
    数据类型 成员变量名N;  
};

使用场景:通常定义一个变量时,比如人,拥有多个特性,名字,年龄, 性别等.这时我们可以定义一个结构体

​​​​eg:

struct person
{
	char name[10];//名字
	int age;//年龄
	char sex;//性别
};

结构体的声明和初始化和使用:

这里我们需要了解两个操作符:结构体引用操作符  .

                                                指向结构体运算符 ->


2.结构体自引用:

定义一个结构体,他的成员里包括和自身成员类型一致的成员

eg:

struct Node
{
	int data;
	struct Node next;
};

3.结构体的内存对齐原则:

先得掌握结构体的 对⻬规则
1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对⻬到某个数字(对⻬数)的 整数倍 的地址处。
对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的 较⼩值。
  注意:VS 中默认的对齐值为 8
-Linux中 gcc 没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩  
3.结构体的总大小为 成员中最大对齐数的整数倍
eg: 我是在vs下测得
struct Person
{
	char name;//1    对齐数1 默认是8 取较小的1
	int age;//4      对齐数4 默认是8 取较小的4
	char sex;//1     对齐数1 默认是8 取较小的1
}person;
int main()
{
	printf("%zd\n", sizeof(person));
	return 0;
}

常规思想此结构体大小应为1+4+1=6个字节

但根据结构体的内存对齐规则实际是12个字节

我们来根据规则计算一下: 1.name的类型是char对齐数是1,占1字节

                                          2.age是int类型,对齐数为4,此时1+4=5字节,但5不是对齐数4的整数倍

                                             所以会多开设3个字节,成为8(4*2)个字节

                                          3.sex是char类型,对齐数是1,8+1=9,但不是最大成员对齐数4的整数倍

                                             所以会多开设3个字节

                                           所以该结构体的大小是1+4+3+1+3=12个字节


但为什么会存在对齐规则,这样做不是会浪费内存空间吗? 大致有两种解释原因:

1. 平台原因 (移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则硬件异常。
2. 性能原因:
数据结构(尤其是栈)应该尽可能地在⾃然边界上对⻬。原因在于,为了访问未对⻬的内存,处理器需要 作两次内存访问;
⽽对⻬的内存访问仅需要⼀次访问。
假设⼀个处理器总是从内存中取8个字节,则地 址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对⻬成8的倍数,那么就可以 ⽤⼀个内存操作来读或者写值了。否则,我们可能需要执⾏两次内存访问,因为对象可能被分放在两
个8字节内存块中。
总体来说:结构体的内存对⻬是拿空间来换取时间的做法

4.结构体传参:

struct S
{
	int data[1000];
	int num;
};
struct S s = { {1,2,3,4}, 1000 };
//结构体传参
void print1(struct S s)
{
	printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps)
{
	printf("%d\n", ps->num);
}
int main()
{
	print2(&s); //传地址
	return 0;
}

两种方式传参:建议使用方法二利用指针来传参,因为传地址不用建立新的函数栈帧(内存空间)


5.结构体实现位段

位段的成员名后边有⼀个冒号和⼀个数字。
注意: 单位是比特位,不是字节
比如: char  a:3  这里指定义一个字符型_a,但只使用3个比特位
初始化一下
根据这个次序结构:则在内存中存放的16进制数是
我们来调试看一下在小端存储的编译器上是不是620304
总结:
跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间但是有跨平台的问题存在
所以不要在不同的编译器上使用位段.

结构体的内容大致就这么多,今天分享到这,

如果你有所收获,可以点点关注爱心收藏

你们的支持是我创作的动力!

  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
引用\[1\]:C语言字节对齐问题详解中提到了C语言中的字节对齐问题。在结构体中,为了提高内存访问的效率,编译器会对结构体进行字节对齐。这意味着结构体的成员在内存中并不是紧凑排列的,而是按照一定的规则进行对齐。具体的对齐规则取决于编译器和编译选项。\[1\] 引用\[2\]:在C语言中,可以使用宏offsetof来获取结构体成员相对于结构体开头的字节偏移量。这个宏非常有用,可以帮助我们计算出每个结构体成员相对于结构体开头的偏移字节数。通过这个宏,我们可以更好地理解结构体的内存布局。\[2\] 引用\[3\]:在C语言中,指针和结构体的组合常常用于处理复杂的数据结构。指针可以指向结构体的成员,通过指针可以方便地对结构体进行操作。指针和结构体的组合可以实现更灵活的数据处理和内存管理。\[3\] 综上所述,C语言中的指针结构体组合可以用于处理复杂的数据结构,而字节对齐问题则是在结构体中为了提高内存访问效率而进行的优化。通过使用宏offsetof,我们可以更好地理解结构体的内存布局。 #### 引用[.reference_title] - *1* *3* [结构体指针,C语言结构体指针详解](https://blog.csdn.net/weixin_34069265/article/details/117110735)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [C语言结构体详解](https://blog.csdn.net/m0_70749276/article/details/127061692)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路过的墙颈鹿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值