笔试遇到很多sizeof的小题,博主基础堪忧,怒总结如下,还是要巩固基础啊啊啊!
sizeof操作符 对象所占 栈内存空间的大小,单位是字节
关键词:char 数组 指针 结构体 class
【注意】
① sizeof(NULL) 结果为1, "\n"转义字符算作1位
② 是栈内存的大小,不是堆,也不是静态全局区
class A1{
public:
int a;
static int b; //静态变量存放在全局数据区域
A1();
~A1();
}; void main(){
cout << sizeof(A1) <<endl; //输出结果 4
}
v
1.基本类型占内存大小
32位机 | 64位机器 | |||
类型 | 字节数 | |||
int | 4 | |||
char | 1 | |||
指针 | 4 | 8 | ||
bool | 1 | |||
float | 4 | 浮点型 | ||
short | 2 | |||
long | 4 | |||
double | 8 | 双精度浮点型 |
2.sizeof(指针) 任意类型指针,结果为4
3.sizeof(数组) 元素大小*n
注意:数组名作为参数传递时,退化为指针,不传值不退化
如 int data[30] = {1,2,3,4};
sizeof(data); //30*4为120
int getSize(int data[ ] ){
return sizeof(data);} // 返回4
4.静态数组vs动态数组
静态数组见上文,动态数组是初始化一个指针
5 sizeof(class)
"类的大小就是类中成员变量(非静态,遵循内存对齐)加上指向虚函数表的指针 以及 指向虚基类表的指针加起来的和。"
一个空类所占空间为 1 ,单继承,多重继承的空类均为 1 ,虚继承的空类设计虚表,虚指针,所以是4
cout<<"空类: " <<sizeof(A) <<endl; //
cout<<"单继承空类: " <<sizeof(C) <<endl; //
cout<<"多继承空类: " <<sizeof(D) <<endl; //1
cout<<"虚单继承空类: " <<sizeof(E) <<endl;//
cout<<"虚多继承空类: " <<sizeof(F) <<endl;//
6.sizeof(函数),对函数的返回值类型,【注意】不能对void操作
7.sizeof( string )
本质上string是一个类,在同一库中相同一点是,无论你的string里放多长的字符串,它的sizeof()都是固定的,字符串所占的空间是从堆中动态分配的,与sizeof()无关。
32位机 vs2008测试 sizeof(string) 为32, 猜测是指针* 4*8=32,为什么??????????
string str="he";
string str1[]={"hello", "program", "world"};
cout <<"string: "<<sizeof(str) <<"\n"<< //
"str1: " <<sizeof(str1) <<"\n"<<endl; //96
8.sizeof(struct) 结构体 字节对齐(以下为转载)
首先,可以用pack预处理指令来禁止字节对齐(很少用到)
#pragma pack(1)
struct a{
char cV;
int iV;
};
#pragma pack()
这是初学者问得最多的一个问题,所以这里有必要多费点笔墨。让我们先看一个结构体:
- struct S1
- {
- char c;
- int i;
- };
问sizeof(s1)等于多少聪明的你开始思考了,char占1个字节,int占4个字节,那么加起来就应该是5。是这样吗你在你机器上试过了吗也许你是对的,但很可能你是错的!VC6中按默认设置得到的结果为8。
扩展:
- struct bs
- {
- char c1;
- char c2;
- int a;
- };
- int main()
- {
- bs t;
- cout<<"sizeof(bs):"<<sizeof(bs)<<endl;//输出sizeof(bs): 8
- cout<<"sizeof(t):"<<sizeof(t)<<endl;//输出sizeof(t): 8
- }
- struct bs
- {
- char c1;
- int a;
- char c2;
- };
- int main()
- {
- bs t;
- cout<<"sizeof(bs):"<<sizeof(bs)<<endl;//输出sizeof(bs): 12
- cout<<"sizeof(t):"<<sizeof(t)<<endl;//输出sizeof(t): 12
- }
Why为什么受伤的总是我请不要沮丧,我们来好好琢磨一下sizeof的定义——sizeof的结果等于对象或者类型所占的内存字节数,好吧,那就让我们来看看S1的内存分配情况:
S1 s1 = { 'a', 0xFFFFFFFF };
定义上面的变量后,加上断点,运行程序,观察s1所在的内存,你发现了什么以我的VC6.0为例,s1的地址为0x0012FF78,其数据内容如下:
0012FF78: 61 CC CC CC FF FF FF FF
发现了什么怎么中间夹杂了3个字节的CC看看MSDN上的说明:
When applied to a structure type or variable, sizeof returns the actual size, which may include padding bytes inserted for alignment.
原来如此,这就是传说中的字节对齐啊!
一个重要的话题出现了。为什么需要字节对齐计算机组成原理教导我们这样有助于加快计算机的取数速度,否则就得多花指令周期了。为此,编译器默认会对结构体进行处理(实际上其它地方的数
据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上,以此类推。这样,两个数中间就可能需要加入填充字节,所以整个结构体的sizeof值就增长了。
让我们交换一下S1中char与int的位置:
- struct S2
- {
- int i;
- char c;
- };
看看sizeof(S2)的结果为多少,怎么还是8再看看内存,原来成员c后面仍然有3个填充字节,这又是为什么啊别着急,下面总结规律。
字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)。
对于上面的准则,有几点需要说明:
1) 前面不是说结构体成员的地址是其大小的整数倍,怎么又说到偏移量了呢因为有了第1点存在,所以我们就可以只考虑成员的偏移量,这样思考起来简单。想想为什么。
结构体某个成员相对于结构体首地址的偏移量可以通过宏offsetof()来获得,这个宏也在stddef.h中定义,如下:
#define offsetof(s,m) (size_t)&(((s *)0)->m)
例如,想要获得S2中c的偏移量,方法为
size_t pos = offsetof(S2, c);// pos等于4
2) 基本类型是指前面提到的像char、short、int、float、double这样的内置数据类型,这里所说的“数据宽度”就是指其sizeof的大小。由于结构体的成员可以是复合类型,比如另外一个结构体,所以在寻找最宽基本类型成员时,应当包括复合类型成员的子成员,而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。
这里叙述起来有点拗口,思考起来也有点挠头,还是让我们看看例子吧(具体数值仍以VC6为例,以后不再说明):
- struct S3
- {
- char c1;
- S1 s;
- char c2
- };
S1的最宽简单成员的类型为int,S3在考虑最宽简单类型成员时是将S1“打散”看的,所以S3的最宽简单类型为int,这样,通过S3定义的变量,其存储空间首地址需要被4整除,整个sizeof(S3)的值也应该被4整除。c1的偏移量为0,s的偏移量呢这时s是一个整体,它作为结构体变量也满足前面三个准则,所以其大小为8,偏移量为4,c1与s之间便需要3个填充字节,而c2与s之间就不需要了,所以c2的偏移量为12,算上c2的大小为13,13是不能被4整除的,这样末尾还得补上3个填充字节。最后得到sizeof(S3)的值为16。
传送门:笔试题【C++基础】 sizeof题目
sizeof与strlen【C++基础】sizeof 与 strlen的区别