sizeof()计算结构体的大小
简要说明:结构体成员按照定义时的顺序依次存储在连续的内存空间,但是结构体的大小并不是简单的把所有成员大小相加,而是遵循一定的规则,需要考虑到系统在存储结构体变量时的地址对齐问题。
一、没有成员的结构体占用的空间是多少个字节?
答案是:1个字节。
这就是实例化的原因(空类同样可以被实例化),每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类或空结构体(C++中结构体也可看为类)隐含的加一个字节,这样空类或空结构体在实例化后在内存得到了独一无二的地址,所以空类所占的内存大小是1个字节。
二、首先介绍一个相关的概念——偏移量
struct stru
{
int a; //start address is 0
char b; //start address is 4
int c; //start address is 8
};
偏移量指的是结构体变量中成员的地址和结构体变量地址的差。结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。显然,结构体变量中第一个成员的地址就是结构体变量的首地址。比如上面的结构体,第一个成员a的偏移量为0。第二个成员b的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;第三个成员c的偏移量是第二个成员的偏移量应该是加上第二个成员的大小(4+1)。
三、在实际中,存储变量时地址要求对齐,编译器在编译程序时会遵循两条原则:
(1)结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
(2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小的公倍数。
例子1:
struct stru1
{
int a; //start address is 0
char b; //start address is 4
int c; //start address is 8
};
PS:用sizeof求该结构体的大小,发现值为12。int占4个字节,char占1个字节,结果应该是9个字节才对啊,为什么呢?这个例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。
例子2:
struct stru2
{
int i; //start address is 0
short m; //start address is 4
};
PS:成员i的偏移量为0;成员m的偏移量为4,都不需要调整。但计算出来的大小为6,显然不是成员m大小的整数倍。因此,编译器会在成员m后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。
例子3、4:
struct stru3
{
char i; //start address is 0
int m; //start address is 4
char n; //start address is 8
};
struct stru4
{
char i; //start address is 0
char n; //start address is 1
int m; //start address is 4
};
虽然结构体stru3和stru4中成员都一样,但sizeof(struct stru3)的值为12而sizeof(struct stru4)的值为8。
由此可见,结构体类型需要考虑到字节对齐的情况,不同的顺序会影响结构体的大小。
四、对于嵌套的结构体,需要将其展开。对结构体求sizeof时,上述两种原则变为:
(1)展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。
(2)结构体大小必须是所有成员大小的整数倍,这里所有成员计算的是展开后的成员,而不是将嵌套的结构体当做一个整体。
例子1:
struct stru5
{
short i;
struct
{
char c;
int j;
} tt;
int k;
};
结构体stru5的成员tt.c的偏移量应该是4,而不是2。整个结构体大小应该是16。
例子2:
struct stru6
{
char i;
struct
{
char c;
int j;
} tt;
char a;
char b;
char d;
char e;
int f;
};
结构体tt单独计算占用空间为8,而stru6的sizeof则是20,不是8的整数倍,这说明在计算sizeof(stru6)时,将嵌套的结构体ss展开了,这样stu6中最大的成员为tt.j,占用4个字节,20为4的整数倍。如果将tt当做一个整体,结果应该是24了。
五:另一个特殊的例子是结构体中包含数组,其sizeof应当和处理嵌套结构体一样,将其展开,如下例子:
struct array
{
float f;
char p;
int arr[3];
};
其值为20。float占4个字节,到char p时偏移量为4,p占一个字节,到int arr[3]时偏移量为5,扩展为int的整数倍,而非int arr[3]的整数倍,这样偏移量变为8,而不是12。结果是8+12=20,是最大成员float或int的大小的整数倍。
测试环境:vc++6.0
测试代码:
//#ifndef __cplusplus
//#endif
#include <iostream>
#include "stdio.h"
#include <stdlib.h>
using namespace std;
struct stru_empty
{
};
struct stru1
{
int a; //start address is 0
char b; //start address is 4
int c; //start address is 8
};
struct stru2
{
int i; //start address is 0
short m; //start address is 4
};
struct stru3
{
char i; //start address is 0
int m; //start address is 4
char n; //start address is 8
};
struct stru4
{
char i; //start address is 0
char n; //start address is 1
int m; //start address is 4
};
struct stru5
{
short i;
struct
{
char c;
int j;
} ss;
int k;
};
struct stru6
{
char i;
struct
{
char c;
int j;
} tt;
char a;
char b;
char d;
char e;
int f;
};
struct stru7
{
char i;
struct
{
char c;
//int j;
} tt;
char a;
char b;
char d;
char e;
int f;
};
struct array
{
float f;
char p;
int arr[3];
};
int main()
{
struct stru6 st6;
struct stru7 st7;
struct array ar;
printf("sizof(char)=%d \n",sizeof(char));
printf("sizof(int)=%d \n",sizeof(int));
printf("sizof(short int)=%d \n",sizeof(short int));
printf("sizof(long int)=%d \n",sizeof(long int));
printf("sizof(long)=%d \n",sizeof(long));
printf("sizof(float)=%d \n\n",sizeof(float));
printf("sizof(stru_empty)=%d \n",sizeof(stru_empty));
printf("sizof(stru1)=%d \n\n",sizeof(stru1));
printf("sizof(stru2)=%d \n\n",sizeof(stru2));
printf("sizof(stru3)=%d \n\n",sizeof(stru3));
printf("sizof(stru4)=%d \n\n",sizeof(stru4));
printf("sizof(stru5)=%d \n\n",sizeof(stru5));
printf("sizof(stru6)=%d \n",sizeof(stru6));
printf("sizof(stru6.tt)=%d \n",sizeof(st6.tt));
printf("the address of stru6.i=%d \n",&st6.i);
printf("the address of stru6.a=%d \n\n",&st6.a);
printf("sizof(stru7)=%d \n",sizeof(stru7));
printf("sizof(stru7)=%d \n",sizeof(st7.tt));
printf("the address of stru7.i=%d \n",&st7.i);
printf("the address of stru7.a=%d \n\n",&st7.a);
printf("sizof(ar)=%d \n",sizeof(ar));
printf("sizof(ar.f)=%d \n",sizeof(ar.f));
printf("sizof(ar.arr)=%d \n",sizeof(ar.arr));
return 0;
}
运行结果:
————————————————
版权声明:本文为CSDN博主「海月汐辰」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37858386/article/details/75909852
sizeof()计算结构体的大小的更多相关文章
- sizeof操作符-结构体与类大小
导读 sizeof是C/C++一个难点,当在自定义类上应用sizeof操作符时,总会出现意想不到的结果,下面,我们就来探讨一下sizeof这个操作符! 目录 1. sizeof与strlen的区别 2 ...
- C-sizeof和strlen区别,以及sizeof如何计算结构体大小
sizeof和strlen区别 sizeof是关键字,在编译时就能计算出值,可以计算任何类型 strlen是函数,只有在运行时才能去计算,且只能计算字符型的. 对于数组时,strlen是判断’\0’为 ...
- 关于结构体占用空间大小总结(#pragma pack的使用)
关于C/C++中结构体变量占用内存大小的问题,之前一直以为把这个问题搞清楚了,今天看到一道题,发现之前的想法完全是错误的.这道题是这样的: 在32位机器上,下面的代码中 class A { publi ...
- 【2017-07-01】Linux应用开发工程师面试问题记录之二:关于结构体的大小及内存对齐问题
Tencent后台服务器开发有一道题是计算一个结构体的sizeof的大小: struct strData { int m_Int; char m_Char; short m_Short; char m ...
- sizeof(结构体) = ?
关于结构体大小怎样计算的文章,我想网上一搜到处都有人总结,本人之所以在此基础上还要发表这样的文章是想用最简单的计算方法来总结前人给出的结论,以致我们在以后在对结构体相关编程中不会陷入字节对齐的陷阱中. ...
- 结构体(struct)大小
结构体(struct)大小 本文参考链接:C语言结构体(struct)常见使用方法,链接中的实例代码经实践有几处不准确,本文在引用时已做更改 注意:在结构体定义时不能申请空间(除非是结构体变量),不可 ...
- YTU 2577: 小数计算——结构体
2577: 小数计算--结构体 时间限制: 1 Sec 内存限制: 128 MB 提交: 978 解决: 647 题目描述 小数可以看成是一个点和两个数组成的,因此可以定义成一个小数的结构体,现在 ...
- sizeof求结构体大小
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...
- 计算结构体、数组、指针的sizeof
1. 结构体的sizeof 题目: sturct aa{ in num; char name[10];}; struct bb{ int a; float b; struct aa c;}; stru ...
随机推荐
- php报错Array to string conversion 解决方案,动态输出数据库列名称
php报错Array to string conversion 解决方案,动态输出数据库列名称 问题:在Windows php5.3环境下使用:<?php echo $row->$keys ...
- vue学习指南:第七篇(详细) - Vue的 组件通信
Vue 的 父传子 子传父 一.父组件向子组件传值: 父传子 把需要的数据 传递给 子组件,以数据绑定(v-bind)的形式,传递到子组件内部,供子组件使用 缩写是(:) 1.创建子组件,在src/ ...
- ucoreOS_lab2 实验报告
所有的实验报告将会在 Github 同步更新,更多内容请移步至Github:https://github.com/AngelKitty/review_the_national_post-graduat ...
- 原生 JavaScript 代替 jQuery【转】
目录 用原生JavaScript代替jQuery Query Selector CSS & Style DOM Manipulation Ajax Events Utilities Promi ...
- 百度云部署SSL证书
查找中间证书 为了确保兼容到所有浏览器,我们必须在阿里云上部署中间证书,如果不部署证书,虽然安装过程可以完全也不会报错,但可能导致Android系统,Chrome 和 Firefox等浏览器无法识别. ...
- Linux 信号量之Posix基于内存的信号量
信号量(semaphore),也和互斥锁一样提供了线程间或者进程间的同步功能. 信号量有三种: Posix有名字的信号量 Posix基于内存的信号量 System V信号量 信号量比互斥锁高级,互斥锁 ...
- 201871010125 王玉江 《面向对象程序设计(Java)》第八周实验总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- soapui学习
另外分享几个公开的Webservice站点,你可以随便招几个服务来测试 http://www.webservicex.net/WS/wscatlist.aspx http://www.service- ...
- 17-numpy笔记-莫烦pandas-5
代码 import pandas as pd import numpy as np left=pd.DataFrame({'key':['K0','K1','K2','K3'], 'A':['A0', ...
- USACO Agri-Net
洛谷 P1546 最短网络 Agri-Net https://www.luogu.org/problemnew/show/P1546 JDOJ 1696: Agri-Net https://neooj ...