首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么structof sizeof不等于每个成员的sizeof总和?

在 C++ 中,structof 是一个关键字,用于将类型信息转换为特定类型的名称,以便于计算结构中的大小和内存分配。sizeof 指令用于计算数据类型或变量在内存中占据的字节数,但是它只能得到类型的总体大小(结构体或类的大小)。因此,我们需要实现一个特殊的结构体来计算 structof 的大小。这个结构体需要包含一个类型指针,一个指向结构体中每个成员的指针数组(用于获取成员的大小),以及一个指向指针数组中相应元素的指针。

这个结构体的实现是基于 C 语言中的 struct 类型的。首先,需要定义一个 structof_type_info 结构体来描述类型信息:

代码语言:c
复制
struct structof_type_info {
    union {
        void *voidptr;
        int dummy[2];
    };
    size_t size;
    struct structof_type_info *next;
};

然后需要实现一个计算 structof_type_info 结构的函数:

代码语言:c
复制
static inline size_t compute_structof_size(const void *type_ptr,
                                           size_t elem_size,
                                           struct structof_type_info **result,
                                           const char *name)
{
    struct structof_type_info *sinfo = *result;
    *result = sinfo;

    char name_buffer[256];
    strncpy(name_buffer, name, sizeof(name_buffer) - 1); // 获取域
    name_buffer[sizeof(name_buffer) - 1] = '\0'; // 将域结束符设置为 null
    structof_info info;

    // 计算结构体整体大小
    info.size = sizeof info - sizeof structof_type_info - elem_size * sizeof(sinfo->next); // 初始化指针数组所在的空间

    // 获取域的大小
    uint8_t field_size;
    offsetof(struct structof_type_info, next) = offsetof(struct structof_type_info, sizeof elem_size * field_size );
    info.next = &structof_info;
    memset(&info.voidptr, 0, sizeof(info.voidptr));

    // 计算结构和每个成员的 sizeof
    while (sinfo->next != NULL) {
        // 计算成员的数量
        offsetof(struct structof_type_info, next) = offsetof(info, next);
        void *base = offsetof(struct structof_type_info, field_size); // 获取成员大小位置
        void *ptr = memcmp(sinfo->next->next, base, offsetof(struct structof_type_info, next) - offsetof(info, next)); // 获取指向成员信息的指针

        // 计算成员类型和大小
        void *base2 = offsetof(struct structof_type_info, sizeof elem_size * field_size); // 获取成员大小位置
        ptr = memcmp(ptr, base2, offsetof(struct structof_type_info, sizeof elem_size * field_size));

        // 计算成员的内存分配
        size_t size = sinfo->next->next - base; // 获取成员大小
        void *data = sinfo->next->next - base; // 获取指向成员信息的指针
        uint8_t field = ptr[0]; // 获取成员信息的位置
        void *ptr2 = offsetof(info, voidptr); // 获取指向成员信息的指针

        // 计算成员的指针和域所占空间
        size_t field_offset = offsetof(info, voidptr) - base2; // 获取指向成员信息的指针
        sinfo->next = sinfo->next->next - field_offset; // 存储指向成员信息的指针
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

为什么结构体 sizeof 不等于每个成员 sizeof 之和

问题 为什么结构体 sizeof 不等于每个成员 sizeof 之和? 回答 失传C结构体打包技艺 — 内存对齐 作者:Eric S....在具有自对齐类型平台上,char、short、int、long 和指针数组都没有内部填充,每个成员都与下一个成员自动对齐。 在下一节我们将会看到,这种情况对结构体数组并不适用。...它跨步地址是 (&p)[2]。于是,在 quad 数组中,每个成员都有 7 字节尾填充,因为下个结构体首个成员需要在8字节边界上对齐。...为了使结构体长度是其最宽成员长度 sizeof(short) 整数倍,接下来进行了填充。...以上两种情况,最好用 sizeof() 来检查存储尺寸。

1.2K20

C++ sizeof()运算符参数为指针和数组为什么不同

sizeof()参数为指针和数组 C++或C语言中,都可以使用sizeof()运算符来计算数组字节大小,除此之外,在C++和C语言中,都可以使用一个指向数组第一个元素内存地址指针来引用数组,因此...,如果要计算数组字节大小,或长度,传递数组本身或传递指向数组指针给sizeof()运算符似乎都是可以,实际上则不然,二者有本质上区别。...int n = sizeof(arr); // 定义一个指针指向数组arr int *p = arr; // 将指针p传递给sizeof() int m = sizeof...这是为什么呢? 不同值原因 这主要是因为当sizeof()运算符参数是数组本身,将计算是数组大小,而如果传递是指针作为参数,那计算便是指针大小,而不是整个数组。...来源:C++ sizeof()参数为指针和数组区别 免责声明:内容仅供参考,不保证正确性。

16121
  • C++:05---class和struct

    为什么不一样呢? struct为空结构体 表示占位为0字节,那么class为空sizeof意义呢: 一个类实例化对象所占空间大小?注意不要说类大小,是类对象大小....如果 Class A; A obj; 那么sizeof(A)==sizeof(obj) 那么sizeof(A)大小和成员大小总和是什么关系呢,很简单,一个对象大小大于等于所有非静态成员大小总和。...为什么是大于等于而不是正好相等呢?...基于上述两点,可以说用sizeof对类名操作,得到结果是该类对象在存储器中所占据字节大小,由于静态成员变量不在对象中存储,因此这个结果等于各非静态数据成员(不包括成员函数)总和加上编译器额外增加字节...(a)<<endl;//result=1 cout<<sizeof(b)<<endl;//result=1 //对象c扩充为2个字,但是对象b为什么没扩充为1个字呢(空类对象一个字节,含一个

    74930

    CC++刁钻问题各个击破之细说sizeof

    (7)sizeof可以对函数调用求大小,并且求得大小等于返回类型大小,但是不执行函数体! (8)sizeof求得结构体(及其对象)大小并不等于各个数据成员对象大小之和!...这个是为什么呢?我一时半会想不到,所以还请朋友们补充! 特性8:sizeof求得结构体(及其对象)大小并不等于各个数据成员对象大小之和!...可以看出sizeof(B)并不等于sizeof(int)+sizeof(double)+sizeof(int)=16。...基于上面三个规则我们来看看为什么sizeof(B)等于24:首先假设结构体首地址为0,第一个成员num1首地址是0(满足规则2,前面无须字节填充,事实上结构体绝对不会在第一个数据成员前面进行字节填充...你或许有很多疑问:为什么要结构体成员对齐,为什么要定义规则1等。如果你有这样疑问,并尝试去弄清楚的话,那么我敢断言,不久将来你必定会有大成就,至少在学习c++上是这样。

    88420

    CC++基础之sizeof使用

    可以看出 sizeof(B) 并不等于 sizeof(int)+sizeof(double)+sizeof(int)=16 。...,只不过顺序不同而已,为什么其大小不一样呢?...结构体大小等于结构体内最大成员大小整数倍 结构体内成员首地址相对于结构体首地址偏移量是其类型大小整数倍,比如说 double 型成员相对于结构体首地址地址偏移量应该是 8 倍数。...从三个规则我们来看看为什么 sizeof(B) 等于 24 :首先假设结构体首地址为0,第一个成员 num1 首地址是 0 (满足规则2),它类型是 int ,因此它占用地址空间 0——3 。...所以每个非静态成员变量在生成新object需要内存,而function是不需要。 3 sizeof 与 strlen 区别 sizeof 是一个操作符,strlen 是库函数。

    35230

    C语言 | C++之sizeof使用

    可以看出 sizeof(B) 并不等于 sizeof(int)+sizeof(double)+sizeof(int)=16 。...,只不过顺序不同而已,为什么其大小不一样呢?...结构体大小等于结构体内最大成员大小整数倍 结构体内成员首地址相对于结构体首地址偏移量是其类型大小整数倍,比如说 double 型成员相对于结构体首地址地址偏移量应该是 8 倍数。...从三个规则我们来看看为什么 sizeof(B) 等于 24 :首先假设结构体首地址为0,第一个成员 num1 首地址是 0 (满足规则2),它类型是 int ,因此它占用地址空间 0——3 。...所以每个非静态成员变量在生成新object需要内存,而function是不需要。 3 sizeof 与 strlen 区别 sizeof 是一个操作符,strlen 是库函数。

    2.7K88

    (虚)继承类内存占用大小

    (虚)继承类内存占用大小 首先,平时所声明类只是一种类型定义,它本身是没有大小可言。 因此,如果用sizeof运算符对一个类型名操作,那得到是具有该类型实体大小。...计算一个类对象大小时规律:     1、空类、单一继承空类、多重继承空类所占空间大小为:1(字节,下同);     2、一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象存储空间...;     3、因此一个对象大小≥所有非静态成员大小总和;     4、当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable...(包括父类非静态数据成员但都不包括所有的成员函数)总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加字节。...(A)<<endl<<sizeof(B)<<endl<<sizeof(C)<<endl<<sizeof(D)<<endl<<sizeof(E); return 0; } ?

    1.6K80

    C语言学习——结构体_联合体_枚举用法直通

    :结构体各个成员会占用不同内存,互相之间没有影响;而共用体所有成员占用同一段内存,修改一个成员会影响其余所有成员。...结构体占用内存大于等于所有成员占用内存总和成员之间可能会存在缝隙),共用体占用内存等于最长成员占用内存。...共用体使用了内存覆盖技术,同一时刻只能保存一个成员值,如果对新成员赋值,就会把原来成员值覆盖掉。...一、为什么要字节对齐    需要字节对齐根本原因在于CPU访问数据效率问题。...联 合 :按其包含长度最大数据类型对齐。    结构体: 结构体中每个数据类型都要对齐。

    56610

    iOS—OC内存对齐原理

    一、获取内存大小三种方式 1.1 sizeOf sizeof是一个操作符,不是函数 sizeof计算内存大小时,传入主要是对象或者数据类型,在编译器编译阶段大小就已经确定 sizeof计算出结果...(myStruct1),sizeof(myStruct2)); (滑动显示更多) 打印结果如下:24-16 结果分析:两个结构体 成员变量是一致,唯一不同成员变量摆放顺序不同,位置不同导致所占内存大小不同...,这就是内存对齐,我们按照内存对齐规则进行分析: 分析结构体myStruct1 【1】a占1字节 从位置0开始 0%1 == 0 0位置存a 【2】b占8字节 从位置1开始 1%8 不等于0 移到8...,内存大小必须为结构体中最大成员8整数倍,32刚刚满足 四、内存优化 思考内存优化 接着上面的结论,我们思考下,为什么要内存对齐,其实苹果这么做目的让cpu读取内存效率更高,用空间换取时间。...:大部分内存都是通过固定内存块进行读取, 尽管我们在内存中采用了内存对齐方式,但并不是所有的内存都可以进行浪费,苹果会自动对属性进行重排,以此来优化内存 五、为什么分配内存大于实际占用内存 通过上面的探索

    56420

    C++小结(1)

    对象所占用空间是其成员变量所用内存总和(可sizeof求证),对象指针指向其首个成员变量地址.对象函数不占用对象内存空间(即使函数中有局部变量) 4. const关键字主要作用是利用编译程序进行排错....和限制对成员改变....必须牢记:引用不等于指针,引用是目标的"别名".对引用操作(包括赋值和&)都是对目标进行. *一个没有初始化指针被称为"失控指针",是非常危险. 6....指针用于: A:处理自由存储区中数据; B:访问类成员数据和成员函数; C:通过引用传递方式给函数传递对象或变量. 7. 关键字new分配堆中内存。...在析构函数中delete指针成员变量,不需要再把指针赋值为0,因为一旦对象消失,作为它成员指针也不能再被访问(当然,赋值0也没害处)

    59890

    作为项目经理,你规划了一份需求技能清单 req_skills, 并打算从备选人员名单 p

    所谓「必要团队」,就是在这个团队中, 对于所需求技能列表 req_skills 中列出每项技能, 团队中至少有一名成员已经掌握。...可以用每个编号来表示团队中成员: 例如,团队 team = [0, 1, 3] 表示掌握技能分别为 people[0],people[1],和 people[3] 备选人员。...请你返回 任一 规模最小必要团队,团队成员用人员编号表示。 你可以按 任意顺序 返回答案,题目数据保证答案存在。...2.初始化变量 n 为 reqSkills 长度,变量 m 为 people 长度,并创建一个长度为 m 整数数组 statuses 用于记录每个技能状态。...3.对于每个人,我们通过比较技能列表和排序后 reqSkills 列表,来确定他们掌握技能状态。首先,将该人技能列表排序。

    19230

    sizeof 操作符详解

    为什么受伤总是我? 请不要沮丧,我们来好好琢磨一下sizeof定义 —— sizeof结果等于对象或者类型所占内存字节数。...再看看内存,原来成员c后面仍然有3个填充字节。 这又是为什么啊?别着急,下面总结规律。...字节对齐细节和编译器实现相关,但一般而言,满足三个准则: 1) 结构体变量首地址能够被其最宽基本类型成员大小所整除; 2) 结构体每个成员相对于结构体首地址偏移量(offset)都是成员大小整数倍...对于上面的准则,有几点需要说明: 1) 前面不是说结构体成员地址是其大小整数倍,怎么又说到偏移量了呢? 因为有了第1点存在,所以我们就可以只考虑成员偏移量,这样思考起来简单。想想为什么。...因为只有非静态类成员变量在新生成一个object时候才需要自己副本。 所以每个非静态成员变量在生成新object需要内存,而function是不需要

    76530

    offset size_c语言sizeof求结构体长度

    原来如此,这就是传说中字节对齐啊!一个重要的话题出现了。为什么需要字节对齐计算机组成原理教导我们这样有助于加快计算机取数速度,否则就得多花指令周期了。...3个填 充字节,这又是为什么啊别着急,下面总结规律。...字节对齐细节和编译器实现相关,但一般而言,满足三个准则: 结构体变量首地址能够被其最宽基本类型成员大小所整除; 结构体每个成员相对于结构体首地址偏移量(offset)都是成员大小整数倍,如有需要编译器会在成员之间加上填充字节...对于上面的准则,有几点需要说明: 1) 前面不是说结构体成员地址是其大小整数倍,怎么又说到偏移量了呢因为有了第1点存在,所以我们就可以只考虑成员偏移量,这样思考起来简单。想想为什么。...联合体sizeof 结构体在内存组织上是顺序式,联合体则是重叠式,各成员共享一段内存,所以整个联合体sizeof也就是每个成员sizeof最大值。

    68010

    C++重要知识点小结---1

    错误:Tdate::void Set(int m , int d , int y) {} 正确: void Tdate::Set(int m , int d , int y) {} 4.一个类对象所占据内存空间由它数据成员所占据空间总和所决定...顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确程序,那么我为什么还要如此看重关键字const呢?我也如下几下理由: 1)....13.在VC中,sizeof有着许多用法,而且很容易引起一些错误。下面根据sizeof后面的参数对sizeof用法做个总结。   ...A.参数为数据类型或者为一般变量:   例如sizeof(int),sizeof(long)等等。   这种情况要注意是不同系统系统或者不同编译器得到结果可能是不同。   ...B.参数为数组或指针:   int a[50]; //sizeof(a)=4*50=200;求数组所占空间大小 int *a=new int[50];// sizeof(a)=4; a为一个指针,sizeof

    78291

    C++运算符执行顺序对照表

    ~ 逻辑非/按位取反 (type) 强制类型转换 * 取指针指向值 & 某某地址 sizeof 某某大小 new,new[] 动态内存分配/动态数组内存分配 delete,....::++-- 调节优先级括号操作符数组下标访问操作符通过指向对象指针访问成员操作符通过对象本身访问成员操作符作用域操作符后置自增操作符后置自减操作符 (a+b)/4;array[4]=2;ptr...~++---+*&(type)sizeof 逻辑取反操作符按位取反(按位取补) 前置自增操作符前置自减操作符一元取负操作符一元取正操作符解引用操作符取地址操作符类型转换操作符返回对象占用字节数操作符...(floatNum); 从右到左 3 ->*.* 在指针上通过指向成员指针访问成员操作符在对象上通过指向成员指针访问成员操作符 ptr->*var=24;obj....= 等于比较操作符不等于比较操作符 if(i==42)...if(i!=42)...

    63220

    完全合并C++面试题

    为什么?...该成员变量占用sizeof(double)=8个字节;接下来为第二个成员dda分配空间,这时下一个能够分配地址对于结构起始地址偏移量为8,是sizeof(char)倍数,所以把dda存放在偏移量为...这时下一个能够分配地址对于结构起始地址偏移量为12,刚好是sizeof(int)=4倍数,所以把type存放在偏移量为12地方,该成员变量占用sizeof(int)=4个字节;这时整个结构成员变量已经都分配了空间...含字段ID,CustomerID(连向Customer中ID外键),Revenue; 写出求每一个CustomerRevenue总和SQL语句。...为什么?? 答: 对 这个 sizeof是编译时运算符,编译时就确定了 能够看成和机器有关常量。

    36820

    C++学习笔记---------基础知识sizeof用法

    但是对于u2和u3,最大空间都是char[13]类型数组,为什么u3大小是13,而u2是16呢?关键在于u2中成员int b。...让我们交换一下S1中char与int位置: struct S2 { int i; char c; }; 看看sizeof(S2)结果为多少,怎么还是8再看看内存,原来成员c后面仍然有3个填充字节,这又是为什么啊别着急...字节对齐细节和编译器实现相关,但一般而言,满足三个准则: 1) 结构体变量首地址能够被其最宽基本类型成员大小所整除; 2) 结构体每个成员相对于结构体首地址偏移量(offset)都是成员大小整数倍...对于上面的准则,有几点需要说明: 1) 前面不是说结构体成员地址是其大小整数倍,怎么又说到偏移量了呢因为有了第1点存在,所以我们就可以只考虑成员偏移量,这样思考起来简单。想想为什么。...联合体sizeof 结构体在内存组织上是顺序式,联合体则是重叠式,各成员共享一段内存,所以整个联合体sizeof也就是每个成员sizeof最大值。

    55810

    动态内存经典笔试题分析及柔性数组

    char* str = NULL; str = GetMemory(); printf(str); } int main() { Test(); return 0; } 这个代码我们看一下,为什么不对呢...然后str肯定不等于NIULL,然后将world赋给str,就会覆盖hello,因此会打印world 柔性数组: 下面我们再给大家将一下什么是柔性数组。 什么是柔性数组?...也许你从来没有听过什么是柔性数组这个概念,但是它的的确确是存在。 在C99中,结构中最后一个元素允许是未知大小数组,这就叫做柔性数组成员。 特点: 结构体中最后一个成员。...}; 柔性数组特点: 1.结构体中柔性数组成员前面必须至少又一个成员 2.sizeof返回这种结构大小不包括柔性数组内存 3.包含柔性数组成员结构用malloc()函数进行内存动态分配...}; int main() { struct S* ps = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int)); return 0; }

    8310
    领券