zoukankan      html  css  js  c++  java
  • 结构体(struct)大小

    结构体(struct)大小

    本文参考链接:C语言结构体(struct)常见使用方法,链接中的实例代码经实践有几处不准确,本文在引用时已做更改

    注意:在结构体定义时不能申请空间(除非是结构体变量),不可以给结构体内部变量初始化

    字节对齐

    对于结构体中比较小的成员,可能被强行对齐,造成空间的空置,但节省了时间。

    #pragma pack()可以修改对齐,它设置了对齐的最大单位

    字节对齐可参考:(记得看完链接后回来往下看哦)

    字节对齐详解
    5分钟搞定字节对齐

    C++结构体派生时的字节对齐

    struct A {
    	int a;
    	char b;
    };
    
    struct B:A {
    	char c;
    	int d;
    	long long e;
    };
    

    在#pragma pack(4) 的情况下, A: 8bytes, B: 24bytes (A:8 + char c:4 + int d:4 + long long e:8 而不是 int a: 4 + char b: 1 + char c: 1 + 2(对齐) + int d: 4 + long long e: 8 = 20)


    struct中的弹性数组

    先看一个例子:

    #include <stdio.h>  
    #include <stdlib>  
    #include <string.h>  
    typedef struct changeable{  
            int iCnt;  
            char fl[0]; //或char fl[] 
    }schangeable;  
      
    main(){  
            printf("size of struct changeable : %d
    ",sizeof(schangeable));  
      
            schangeable *pchangeable = (schangeable *)malloc(sizeof(schangeable) + 10*sizeof(char));  
            printf("size of pchangeable : %d
    ",sizeof(*pchangeable));  
      
            schangeable *pchangeable2 = (schangeable *)malloc(sizeof(schangeable) + 20*sizeof(char));  
            pchangeable2->iCnt = 20;  
            printf("pchangeable2->iCnt : %d
    ",pchangeable2->iCnt);  
            strncpy(pchangeable2->fl,"hello world",11);  
            printf("%s
    ",pchangeable2->fl);  
            printf("size of pchangeable2 : %d
    ",sizeof(*pchangeable2)); 
    }
    
    //  结构体中的 char pc[0] 可以通过malloc方法(堆空间)变为可增长的
    size of struct changeable : 4  
    // 注意:分配了空间之后的结构体大小依旧是4,弹性数组依然不占空间
    size of pchangeable : 4  
    pchangeable2->iCnt : 20  
    hello world  
    size of pchangeable2 : 4 
    

    读者可能会疑惑 char fl[0] 在这里的意义,实际上,这是一个弹性数组,它使这个结构体变成了有意义的可变长结构体,而这里的变长实际上是堆空间

    弹性数组在结构体中,下面的形式是唯一允许的(非弹性数组不能用"char a[]"这种形式定义,必须明确大小)

    struct s {
    	int a;
    	char b[];
    }
    

    顺序颠倒可能会让b和a数据重合(见补充);少了变量a又会让整个结构体长度为0(弹性数组不占空间),编译不能通过。

    C如果有空结构体,定义两个或多个该结构体的变量(对象),地址是完全一样的!调试看程序运行,这些语句其实根本没有运行,没有实际意义。
    C++形式上是允许空结构体的,本质上是通过机制避免了纯空结构体和类对象,自动给空结构体对象分配一个字节(sizeof()返回1)方便区分对象,避免地址重合。
    例外的是,C++唯独不给带弹性数组的结构体分配空间(可能怕和变长结构体机制产生某种冲突,比如大小怎么算)
    下面两个结构体在C++中是不一样的,空的结构体反而“大”(sizeof()返回1)
    struct s  
    {  
            char b[] ;  
    };  
    
    struct s  
    {  
    //        char b[] ;  
    };
    

    补充

    字符串覆盖

    看懂下面这个例子即可

    #include <stdio.h>  
    #include <string.h>  
      
    typedef struct{  
    int iTest;  
    char pcArray[20];  
    int iParam;  
    }s;  
      
    main(){  
            s s1;  
            s1.iParam = 5;  
            s1.iTest = 6;  
            printf("iTest:	%p:%d
    ",&s1.iTest,s1.iTest);  
            printf("iParam:	%p:%d
    ",&s1.iParam,s1.iParam);  
            strncpy(s1.pcArray,"Hello World,Hello World",23);  
            printf("pcArray:	%p:%s
    ",&s1.pcArray,s1.pcArray);  
            printf("iTest:	%p:%d
    ",&s1.iTest,s1.iTest);  
            printf("iParam:	%p:%d
    ",&s1.iParam,s1.iParam);  
    } 
    

    结果如下

    iTest:  0xbfbebc64:6  
    iParam: 0xbfbebc7c:5  
    // 实际上,运行到这里是可能会报错,因为会字符串赋值操作溢出了
    pcArray:    0xbfbebc68:Hello World,Hello World  
    iTest:  0xbfbebc64:6  
    iParam: 0xbfbebc7c:6581362
    

    这个例子告诉我们,数组还是放在结构体的末尾比较保险……

    update at 2017/9/16
    by 一颗球

  • 相关阅读:
    (二十三)、int与integer的区别
    (二十一)、Java序列化与反序列化
    (二十)、MVC设计思想的优缺点
    (十九)、列出自己常用的JDK包
    (十八)、Session与Cookie区别
    win10 下安装laravel
    冒泡排序
    常用php正则表达式
    AE网站
    AE压缩网站
  • 原文地址:https://www.cnblogs.com/chunzhulovefeiyue/p/7532881.html
Copyright © 2011-2022 走看看