07|整合数据:枚举、结构与联合是如何实现的?
该思维导图由 AI 生成,仅供参考
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了C语言中枚举、结构和联合的实现原理。首先,枚举类型在C语言中被编译为int类型,但存在一些潜在问题。其次,结构类型在内存中的布局并非严格连续,编译器会进行数据对齐以满足CPU的最高效率读写需求。文章通过C代码和对应的汇编代码展示了枚举和结构类型的实现细节,以及内存数据对齐的重要性。最后,联合是一种特殊的复合数据类型,内部定义的所有数据字段将占用同一块内存空间。总结来说,本文通过深入分析编译器对这三种数据类型的实现方式,为读者提供了对C语言中数据类型底层实现原理的深入理解,为编写高质量程序提供了有益的参考。
《深入 C 语言和程序运行原理》,新⼈⾸单¥59
全部留言(15)
- 最新
- 精选
- zxk共 24 字节: 1. short a、char b、char c 共 2 + 1 + 1 = 4 bytes; 2. padding = 4 bytes; 3. int* d 为 8 bytes; 4. 联合大小取决于最大的 double,为 8 byes; 综上,共为 2 + 1 + 1 + 4 + 8 + 8 = 24 bytes。
作者回复: 回答正确!
2022-01-2211 - Pushsadfc老师,那个关于c语言如何构建项目或者编程规范的书有推荐的咩
作者回复: 有一本叫《C in a Nutshell: The Definitive Reference》的书,不知道符不符合你的需求。
2022-01-022 - liu_liua - 2 字节 b - 1 c - 1 padding - 4 d - 8 union - 8 共 24 字节。 ------- 但老师,我有些地方不太明白。 当给思考题中的结构体赋值(我给它起名叫 User),并且 union 赋值为浮点数 1.25,如下: int main() { struct User u = {1, 'a', 'b', 0x10000, .e = 1.25}; return 0; } 汇编代码如下: ------ main: push rbp mov rbp, rsp mov WORD PTR [rbp-32], 1 mov BYTE PTR [rbp-30], 97 mov BYTE PTR [rbp-29], 98 mov QWORD PTR [rbp-24], 65536 movsd xmm0, QWORD PTR .LC0[rip] movsd QWORD PTR [rbp-16], xmm0 mov eax, 0 pop rbp ret .LC0: .long 0 .long 1072955392 -------- .LC0 这段应该是浮点数 1.25 的值。 movsd xmm0, QWORD PTR .LC0[rip],我猜它的含义是把 1.25 的值放入 xmm0 寄存器中。 1. 那 .LC0[rip] 的意思是什么呢?为什么要把 rip 传入呢? 2. 为什么 .LCO 中使用两个 .long 来表示呢?这里的具体含义是什么呢? 望老师解答~
作者回复: 很好的问题!下面是回答: 1. 这里的 “.LC0[rip]” 实际上是汇编代码中的一种通过 rip 寄存器来进行相对寻址的方式,一般也称为 pc-relative 或 rip-relative。rip 寄存器中存放着下一条将要执行的指令。而这里该条指令的寻址结果便是 .LC0 这个 label 的开头。 2. .long 是一个汇编指示标记,用于让汇编器在当前这个位置保留一个 4 字节的值。这里第一个 .long 0 是 1.25 对应二进制表示的低 32 位;第二个 .long 1072955392 则是对应高 32 位的十进制值。
2021-12-2232 - sky问答题,X86_64架构下,24字节。综合考虑两个点: 1.结构体 内部成员 自然对齐; 2.结构体数组的内存对齐。
作者回复: 正确!
2021-12-221 - pedrox86_64 的平台下,sizeof 得到的大小为:24 = 8 + 8 + 8, 加上 packed 属性后,sizeof 为 20 = (1 + 1 + 2) + 8 + 8。
作者回复: 没错!
2021-12-221 - tanatang"因此,让枚举类型有助于组织程序代码的同时并确保它不被乱用,也是我们在构建高质量程序时需要注意的一个问题。" 这个具体怎么做呢? 比如将 foo()入参定义为 枚举类型。 但是调用 foo(3) 或者 int i= 6;foo(i)。 一样可以编译执行。
作者回复: 是的,你举的例子就是一个乱用的方式。编译器实际上有很大的宽容性,可以允许各种样式的代码通过编译,但在代码组织层面,各种语法结构怎么使用,需要团队整体有一个规范来约束。就比如你既然用枚举了,那就不要直接传数字,而是应该用带有业务含义的枚举值,等等。
2023-02-08归属地:四川 - may_huang老师有比较好的讲汇编的书推荐吗?代码中有些汇编代码不是很懂。
作者回复: 可以看看有关 x86 汇编的书,推荐一本入门的:《x86汇编语言:从实模式到保护模式》,进阶一点可以看《X86/X64 体系探索及编程》。
2022-08-03归属地:北京2 - 好吃不贵可以用gdb的ptype来查看各字段的大小。 ptype /o a /* offset | size */ type = struct { /* 0 | 2 */ short a; /* 2 | 1 */ char b; /* 3 | 1 */ char c; /* XXX 4-byte hole */ /* 8 | 8 */ int *d; /* 16 | 8 */ union { /* 8 */ double e; /* 4 */ int f; /* total size (bytes): 8 */ }; /* total size (bytes): 24 */ }
作者回复: 👍🏻
2022-06-15 - 张贺40个字节
作者回复: 不对哦,再看看?
2021-12-22 - =x86-64 gcc 11.2编译器下,为24bytes。 short类型的a占用2bytes; char类型的b占用1bytes,此时满足自然对齐; char类型的c占用1bytes,此时满足自然对齐; 指针类型的d占用8bytes,此时不满足自然对齐,需要先填充4bytes的padding,然后再放置8bytes的d; 联合的大小与double类型保持一致,因此是8bytes,此时满足自然对齐。 综上,总共是2+1+1++4+8+8=24bytes2022-01-0526