【C语言】这种求结构体成员大小的方法,你可能需要了解一下~
在C语言编程中,有时候需要知道某结构体中某成员的大小,比如使用堆内存来存储结构体中的某成员时,需要知道该成员的大小,才好确定所需申请的空间大小。求某结构体中某成员的大小,你会怎么做?
例子:
typedef struct { char a; char c; short b; int d; char e; }test_struct;
求 d 成员所占内存空间的大小。
方法一
萌新尝试法。。。
我们可以先定义一个结构体变量,然后再使用sizeof求出。
#include <stdio.h> typedef struct { char a; char c; short b; int d; char e; }test_struct; int main(void) { test_struct test_s; printf("sizeof(test_s.d) = %d\n", sizeof(test_s.d)); return 0; }
运行结果:

但是我们为了得到一个成员的大小,而专门定义一个结构体变量,而这个变量也没有其它的用途,有点浪费资源,或者说这种方法low了。
方法二
肉眼观察法。。。
比如在32bit环境下,我们一眼看出d是int类型,就是4个字节,使用sizeof(int)求出。然后想咋用就咋用。这个简单就不讨论了。
方法三
装X法。。。
代码:
#include <stdio.h> typedef struct { char a; char c; short b; int d; char e; }test_struct; int main(void) { printf("sizeof(((test_struct*)0)->d) = %d\n", sizeof(((test_struct*)0)->d)); printf("sizeof(((test_struct*)0)->a) = %d\n", sizeof(((test_struct*)0)->a)); printf("sizeof(((test_struct*)0)->b) = %d\n", sizeof(((test_struct*)0)->b)); printf("sizeof(((test_struct*)0)->c) = %d\n", sizeof(((test_struct*)0)->c)); return 0; }
运行结果:

类似 ((test_struct*)0)->d 这样的用法是个固定用法,把0地址转换为test_struct结构的指针,对于结构体指针,使用 -> 符号就是取其成员,再使用sizeof就可以求得其大小。这里不一定是0地址,其它地址也可以,但一般都会使用0地址。这种方法较方法一的好处就是不用定义一个多余的变量。
这种方法很重要,需要掌握,可能你平时编程不会使用这种方法,但这种方法很重要。在很多优秀的代码中会出现类似形式的宏代码,例如:
上例可封装一个宏定义:
#define MEM_SIZE(type, member) sizeof(((type*)0)->member)
求某成员在结构体中的偏移量:
#define OFFSETOF(type, member) ( (size_t)(&( ( (type*)0)->member ) ) )
求结构体偏移量在C语言头文件中 stddef.h 也有提供,使用方法如:
#include <stdio.h> #include <stddef.h> #define OFFSETOF(type, member) ( (size_t)( &( ( (type*)0 )->member ) ) ) typedef struct { char a; char c; short b; int d; char e; }test_struct; int main(void) { /* stddef.h宏 */ printf("offset(a): %d\n", offsetof(test_struct, a)); printf("offset(c): %d\n", offsetof(test_struct, c)); printf("offset(b): %d\n", offsetof(test_struct, b)); printf("offset(d): %d\n", offsetof(test_struct, d)); printf("offset(e): %d\n", offsetof(test_struct, e)); /* 自定义宏 */ printf("OFFSETOF(a): %d\n", OFFSETOF(test_struct, a)); printf("OFFSETOF(c): %d\n", OFFSETOF(test_struct, c)); printf("OFFSETOF(b): %d\n", OFFSETOF(test_struct, b)); printf("OFFSETOF(d): %d\n", OFFSETOF(test_struct, d)); printf("OFFSETOF(e): %d\n", OFFSETOF(test_struct, e)); return 0; }
运行结果:

使用这个求结构体偏移量的宏我们就可以很好地知道结构体成员的在内存中的存储情况。
以上就是本次分享的求结构体成员的三种方法。重点掌握方法三,因为在很多优秀的代码中都有使用到类似的方法。
如有错误,欢迎指出!谢谢~
看到这里是不是又学到了很多新知识呢~
如果你很想学编程,小编推荐我的C语言/C++编程学习基地【点击进入】!
都是学编程小伙伴们,带你入个门还是简简单单啦,一起学习,一起加油~
还有许多学习资料和视频,相信你会喜欢的!
涉及:游戏开发、常用软件开发、编程基础知识、课程设计、黑客等等......


【C语言】这种求结构体成员大小的方法,你可能需要了解一下~的更多相关文章
- 指针直接赋值为整型AND利用宏定义求结构体成员偏移量
首先我们要更正一个很熟悉的概念,那就是指针不仅仅是“地址”,指针还有一个很重要的特性,那就是“类型”. 指针初始化时,“=”的右操作数; 除外,该语句表示指针为空): 所以 ; 这样的代码是不允许的. ...
- 怎样求结构体成员的偏移地址 || 结构体的 sizeof 总结
C 语言中同意将值为 0 的变量强制转换成任一类型的指针,转换结果是一个NULL指针. (type*)0 // 一个 type 类型的NULL指针 用这个指针訪问结构体内的成员是非法的,可是 & ...
- C语言中访问结构体成员时用‘.’和‘->’的区别
举个例子,定义了一个叫Student,别名为stu的结构类型,我们声明了一个结构体变量叫stu1,声明了一个结构体指针为stuP. typedef struct Student { char name ...
- go语言基础之结构体成员的使用指针变量
1.结构体成员的使用:指针变量 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct ...
- go语言基础之结构体成员的使用普通变量
1.结构体成员的使用普通变量 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...
- C语言:存取结构体成员的点运算符(.)和箭头运算符(->)的区别
转自:http://blog.csdn.net/taric_ma/article/details/7397362 一直以为这两个是没有什么区别的,可以相互替换,今天又翻了一下<C语言核心技术&g ...
- offset求结构体成员的偏移量
[代码] C++ Code 12345678910111213141516171819202122232425262728293031 /* version: 1.0 author: hell ...
- struct的成员对齐问题-结构体实际大小问题
struct的成员对齐 注意:为了方便说明,等号左边是每个数据单独所占长度,右边是最终空间大小,以字节为单位. 一.什么时间存在对其问题:(32位机对齐方式是按照4字节对其的,以下所有试验都是在32位 ...
- 关于C语言中结构体中的结构体成员导致的字节对齐问题
关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/ 这里的结构体字节对齐的数据类 ...
随机推荐
- Java使用ArrayList实现“群主发红包”功能
群主发普通红包,某群有多名成员,群主给成员发普通红包,普通红包的规则: 群主的一笔金额,从群主余额中扣除,平均分成n等份,让成员领取: 成员领取红包后,保存到成员余额中. 请根据描述,完成案例中所有类 ...
- Kubernetes的资源控制器和Service(四)
一.定义和分类 1,定义 k8s 中内建了很多控制器(controller ),这些相当于一个状态机,用来控制 Pod 的具体状态和行为. 2,类型 ReplicationController.Rep ...
- jzoj 6798. 【2014广州市选day2】regions
Description 在平面上堆叠着若干矩形,这些矩形的四边与平面X坐标轴或Y坐标轴平行.下图展示了其中一种情况,3个矩形的边将平面划分成8个区域: 下面展示了另一种稍稍复杂一些的情况: 你的任务是 ...
- Solon详解(七)- Solon Ioc 的注解对比Spring及JSR330
Solon详解系列文章: Solon详解(一)- 快速入门 Solon详解(二)- Solon的核心 Solon详解(三)- Solon的web开发 Solon详解(四)- Solon的事务传播机制 ...
- Blocks(POJ 3734)
原题如下: Blocks Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8020 Accepted: 3905 Desc ...
- 架构设计 | 基于Seata中间件,微服务模式下事务管理
源码地址:GitHub·点这里 || GitEE·点这里 一.Seata简介 1.Seata组件 Seata是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务.Seata将为用 ...
- linux系统的默认用户
1.可以通过cat /etc/passwd |cut -f1 -d: 可以提取/etc/passwd文件的第一个字段 2.也可以通过vipw进入vi编辑器来查看该文件每一行的第一个字段 linux ...
- oracle之三RMAN概述
RMAN概述 6.1 rman的定义和功能: 1) Recovery Manager 2)建立备份和恢复的server process,在oracle server上做备份和恢复 3)rman 备份d ...
- [LeetCode]66. 加一(数组)
###题目 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一. 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字. 你可以假设除了整数 0 之外,这个整数不会以零开头. 示例 ...
- nginx实战(1):宝塔设置反向代理
以下操作适用于默认80端口转其他地址非80端口情况. 添加网站 注意:因我只是拿来当反向代理来使用,所PHP为纯静态模式. 开启反向代理 注:目标URL为最终目的地,发送域名为默认,如设置后无效则修改 ...