结构体(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\n",sizeof(schangeable)); schangeable *pchangeable = (schangeable *)malloc(sizeof(schangeable) + 10*sizeof(char));
printf("size of pchangeable : %d\n",sizeof(*pchangeable)); schangeable *pchangeable2 = (schangeable *)malloc(sizeof(schangeable) + 20*sizeof(char));
pchangeable2->iCnt = 20;
printf("pchangeable2->iCnt : %d\n",pchangeable2->iCnt);
strncpy(pchangeable2->fl,"hello world",11);
printf("%s\n",pchangeable2->fl);
printf("size of pchangeable2 : %d\n",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:\t%p:%d\n",&s1.iTest,s1.iTest);
printf("iParam:\t%p:%d\n",&s1.iParam,s1.iParam);
strncpy(s1.pcArray,"Hello World,Hello World",23);
printf("pcArray:\t%p:%s\n",&s1.pcArray,s1.pcArray);
printf("iTest:\t%p:%d\n",&s1.iTest,s1.iTest);
printf("iParam:\t%p:%d\n",&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 一颗球

结构体(struct)大小的更多相关文章

  1. 结构体struct 与 联合union

    1.C语言中的结构体 1.1 定义 结构体是由一系列相同或不同类型的变量组成的集合. struct 结构体名{               //struct为关键字,“结构体名”为用户定义的类型标识. ...

  2. C语言结构体-struct

    知识点: 1)结构体的定义. 2)结构体的sizeof. 3)  结构体的指针. 1) 结构体的定义: 在逻辑上有一定关联的多个数据类型做为一整体进行操作的数据结构,它的关键字是struct.下面我将 ...

  3. Go语言学习笔记(四)结构体struct & 接口Interface & 反射

    加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struc ...

  4. 结构体struct sockaddr_in, struct sockaddr,struct in_addr

    一.结构体 struct sockaddr_in,  struct sockaddr,  struct in_addr struct sockaddr_in,  struct sockaddr,str ...

  5. 结构体struct、联合体union、枚举类型enum

    1.c语言中的类型 1)内置类型——char,short,int,float,double: 2)用户自定义类型(UDT)——struct结构体,union联合体,enum枚举类型 2.内存对齐 2. ...

  6. Go语言学习笔记(四)结构体struct & 接口Interface & 反射reflect

    加 Golang学习 QQ群共同学习进步成家立业工作 ^-^ 群号:96933959 结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套: go中的struc ...

  7. C# 结构体 struct

    C# 结构体 struct C#中结构类型和类类型在语法上非常相似,他们都是一种数据结构,都可以包括数据成员和方法成员. 结构和类的区别: 1.结构是值类型,它在栈中分配空间:而类是引用类型,它在堆中 ...

  8. C++基础---结构体(struct)

    转自:http://blog.csdn.net/cainv89/article/details/48447225 1. 结构体(struct) 1.1 结构体的概念 结构体(struct):是由一系列 ...

  9. 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf

    转载请注明出处:windeal专栏 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq  结构体struct ifconf来获取网络接口的各种信息. ioctl 首先看 ...

随机推荐

  1. 在自学java路上遇上的南墙

    从2016年12月20号自学java,先是咨询了下培训中心,得小两万,四个月毕业,算了一笔账,一百二十天,合下来每天三百多块,再加上开销之类压力太大,于是开始入坑自学,随后血一般的教训直面而来: 1. ...

  2. HDU--1358--KMP算法失配函数getfail()的理解--Period

    /* Name: hdu--1358--Period Author: 日天大帝 Date: 20/04/17 10:24 Description: 长度/向后移动的位数 = 出现的次数 kmp其实匹配 ...

  3. Springboot+redis 整合

    运行环境: JDK1.7. SpringBoot1.4.7 redis3.0.4 1.生成Springboot项目,分别添加web,redis依赖,具体的maven依赖如下 <dependenc ...

  4. 2.ssh密钥登陆(ssh无密码登陆)

    1.A主机生成密钥对 ssh-keygen  -t  rsa 2.将A主机的公钥发给B主机 scp  id_rsa.pub  linux2:/cloud                         ...

  5. JavaScript 排序算法(JavaScript sorting algorithms)

    JavaScrip 排序算法(JavaScript Sorting Algorithms) 基础构造函数 以下几种排序算法做为方法放在构造函数里. function ArrayList () { va ...

  6. connect by prior 递归算法

    http://blog.163.com/xxciof/blog/static/7978132720095193113752/ oracle中 connect by prior 递归算法 Oracle中 ...

  7. Python 装饰器总结

    装饰器总结 前提 使用装饰器的前提在于Python提供的特性: 函数即对象,可以进行传递: 函数可以被定义在另外一个函数中: 可以通过一个例子来了解: def get_animal(name='dog ...

  8. JS进阶 ] 分析JS中的异步操作

    写在前面 JS因为是单线程的,所以在执行事务的时候,往往会因为某个事务的延迟,而导致服务器假死,这时候异步编程就显的格外重要,但是异步编程一般理解为回调函数callback,典型的就是node,回调函 ...

  9. ccache - 让Xcode编译速度飞起来

    今天来介绍一个小工具ccache,其可以提高xcode的编译速度.说起缘由,是因为我的苹果电脑配置比较低,而每次开发调试或测试打包都需要编译工程,虽然项目工程代码量不算大,但是编译的时间还是很长,尤其 ...

  10. 关于InnoDB存储引擎text和blob类型的优化

    我们在数据库优化的时候,看到一些表在设计上使用了text或者blob的字段,如果单表的存储空间达到了近上百G或者大几十G,这种情况再去改变和优化就非常难了 一.简介 为了清楚大字段对性能的影响,我们有 ...