在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语言】这种求结构体成员大小的方法,你可能需要了解一下~的更多相关文章

  1. 指针直接赋值为整型AND利用宏定义求结构体成员偏移量

    首先我们要更正一个很熟悉的概念,那就是指针不仅仅是“地址”,指针还有一个很重要的特性,那就是“类型”. 指针初始化时,“=”的右操作数; 除外,该语句表示指针为空): 所以 ; 这样的代码是不允许的. ...

  2. 怎样求结构体成员的偏移地址 || 结构体的 sizeof 总结

    C 语言中同意将值为 0 的变量强制转换成任一类型的指针,转换结果是一个NULL指针. (type*)0 // 一个 type 类型的NULL指针 用这个指针訪问结构体内的成员是非法的,可是 & ...

  3. C语言中访问结构体成员时用‘.’和‘->’的区别

    举个例子,定义了一个叫Student,别名为stu的结构类型,我们声明了一个结构体变量叫stu1,声明了一个结构体指针为stuP. typedef struct Student { char name ...

  4. go语言基础之结构体成员的使用指针变量

    1.结构体成员的使用:指针变量 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct ...

  5. go语言基础之结构体成员的使用普通变量

    1.结构体成员的使用普通变量 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...

  6. C语言:存取结构体成员的点运算符(.)和箭头运算符(->)的区别

    转自:http://blog.csdn.net/taric_ma/article/details/7397362 一直以为这两个是没有什么区别的,可以相互替换,今天又翻了一下<C语言核心技术&g ...

  7. offset求结构体成员的偏移量

    [代码]  C++ Code  12345678910111213141516171819202122232425262728293031   /* version: 1.0 author: hell ...

  8. struct的成员对齐问题-结构体实际大小问题

    struct的成员对齐 注意:为了方便说明,等号左边是每个数据单独所占长度,右边是最终空间大小,以字节为单位. 一.什么时间存在对其问题:(32位机对齐方式是按照4字节对其的,以下所有试验都是在32位 ...

  9. 关于C语言中结构体中的结构体成员导致的字节对齐问题

    关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/ 这里的结构体字节对齐的数据类 ...

随机推荐

  1. touchstart 事件与 click 事件的冲突

    const clickEvent = (function() {   if ('ontouchstart' in document.documentElement === true)     retu ...

  2. odoo10甘特图gantt view

    odoo10中的gantt图示例 1.Gantt属性说明 甘特图视图的根元素是<gantt />,它没有子节点但可以采用以下属性: date_start (required) 提供每条记录 ...

  3. linux 字符驱动框架(用户态的read,write,poll是怎么操作驱动的)

    前言 这篇文章是通过对一个简单字符设备驱动的操作来解释,用户态的读写操作是怎么映射到具体设备的. 因为针对不同版本的linux内核,驱动的接口函数一直有变化,这贴出我测试的系统信息: root@ubu ...

  4. [算法]体积不小于V的情况下的最小价值(0-1背包)

    题目 0-1背包问题,问要求体积不小于V的情况下的最小价值是多少. 相关 转移方程很容易想,初始化的处理还不够熟练,可能还可以更简明. 使用一维dp数组. 代码 import java.util.Sc ...

  5. 使用App Metrics实现性能监控

    App Metrics监控需要安装InfluxDB时序数据库和Grafana可视化分析工具 1.安装InfluxDB 下载地址:https://portal.influxdata.com/downlo ...

  6. ActiveMQ客户端Apache.NMS从.net 4.0移植到.net standard 2.0

    1.从官网或GitHub下载Apache.NMS源码 2.新建.net standard 2.0类库 3.将源码复制到新建的类库中,并删除或注释CommonAssemblyInfo.cs文件(程序集版 ...

  7. Java io实现读取文件特殊内容进行替换

    最近公司在做一个项目其中一个需求是读取文件中的特殊字符在其后进行添加或删除字符操作,本来想直接使用randomAccessFile按行读取,读取到特殊字符就进行添加或删除操作,但是randomAcce ...

  8. 本机浏览器无法访问linux的tomcat

    原因:Centos7的防火墙拦截了tomcat访问的8080端口  Redhat 等等linux firewall-cmd --permanent --zone=public --add-port=8 ...

  9. Centos-归档文件或目录-tar

    tar 对文件或者目录进行打包归档成一个文件,不是压缩 相关选项 -c 新建文件 -r 将目标文件追加都档案文件末尾 -t 列出归档文件中已经归档文件列表 -x 从归档文件中还原文件 -u 新文件更新 ...

  10. Python实现的数据结构与算法之双端队列详解

    一.概述 双端队列(deque,全名double-ended queue)是一种具有队列和栈性质的线性数据结构.双端队列也拥有两端:队首(front).队尾(rear),但与队列不同的是,插入操作在两 ...