【C++学习笔记】sizeof()的用法与字节对齐

1.32位机器和64位机器下面各类型sizeof的大小。

1) 32位机器下:

Char类型:

Size of charis:                            1

Size of unsigned charis:              1

Size of signed charis:           1

整型:

Size of intis:                       4

Size of shortis:                    2

Size of longis:                     4

Size of long intis:                4

Size of signed intis:             4

Size of unsigned intis:          4

Size of unsigned long intis:         4

Size of long long intis:                8

Size of unsigned long longis:       8

浮点型:

Size of floatis:                    4

Size of doubleis:                 8

Size of long doubleis:          8

指针:

Size of (void *) is:         4    

Size of (char *) is:         4

Size of (int *)is:             4

Size of (long *)is:          4

Size of (long long *) is:   4

Size of (float *)is:          4

Size of (double *)is:       4

2) 64位机器下

Char类型:

Size of charis:                            1

Size of unsigned charis:                1

Size of signed charis:                  1

整型:

Size of intis:                                    4

Size of shortis:                                2

Size of longis:                                  8

Size of long intis:                             8

Size of signed intis:                           4

Size of unsigned intis:                       4

Size of unsigned long intis:                8

Size of long long intis:                       8

Size of unsigned long longis:              8

浮点型:

Size of floatis:                    4

Size of doubleis:                 8

Size of long double is:          16

指针:

Size of (void *)is:           8

Size of (char *)is:           8

Size of (int *)is:             8

Size of (long *)is:           8

Size of (long long *) is:   8

Size of (float *)is:          8

Size of (double *)is:              8

注意:32位机器和64位机器的区别:1)long从4字节变为8字节;2)long double从8字节变为16字节;3)指针从4字节变为8字节,这是因为指针是指向元素的地址,地址从4字节变为8字节,指针自然也会跟着变化。

2.字节对齐的概念

字节对齐:计算机存储系统中以Byte为单位存储数据,不同数据类型所占的空间不同。计算机为了快速的读写数据,默认情况下将数据存放在某个地址的起始位置,如整型数据(int)默认存储在地址能被4整除的起始位置,字符型数据(char)可以存放在任何地址位置(被1整除),短整型(short)数据存放在地址能被2整除的起始位置。这就是默认字节对齐的方式。

3.数组的大小计算

1)对数组执行sizeof运算得到整个数组所占空间的大小,等价于对数组中所有的元素各执行一次sizeof运算并将所得结果求和。注意:sizeof运算不会把数组转化成指针来处理。

如:

char ch[10] = “abcdef”;

cout<<sizeof(ch)<<endl;

cout<<sizeof(*ch)<<endl;

程序运行结果为10和1。因为sieof运算时不会把数组转化为指针来处理,因此sizeof(ch)为10。ch*指向的是字符串的首地址的值,也就是a。因此sizeof(*ch)的值为1。

2)对string对象或vector对象执行sizeof运算只返回该类型固定部分的大小,不会计算对象中的元素占用了多少空间。

如:

vector<int> vec(5);

vec.push_back(9);

cout<<sizeof(vec)<<endl;

程序运行结果为20。这是因为vector的底层实现就是数组,声明vec(5)就相当于已经分配了5个int类型的地址。因此sizeof(vec)的的小为5*4=20。

3)对于函数传递的参数为数组的,因为在传递过程中,实际上是以指针的形式来传递的。因此,它的大小为指针的大小4。

如:

void print(char a[])

{

    cout<<sizeof(a)<<endl;

}

int _tmain(int argc, _TCHAR* argv[])

{

    char ch[10]=”abc”;

    print(ch);

}

4.union和struct的大小计算

1)union大小计算:

对于union,对齐的大小是最大的基本元素的对齐大小;对象的大小必须是该基本元素大小的整数倍;同时要满足实际大小不能小于最大成员的大小。

2)union大小计算举例:

如:

Union U1
{
	char a[9];
	int b;
};

成员a是char类型,对齐大小为1字节,成员b是int类型,对齐大小是4,所以该union的对齐大小是4。大小为大于等于max(9,4)=9并为4的整数倍,所以是12字节。

3)struct大小计算

先算出struct的对齐大小,对齐的大小也是取决于struct成员中字节对齐最大的那个;然后根据每个成员的对齐大小对每个成员算出分配的空间;最后算出struct实际分配的空间,在满足对齐每个成员的基础上,满足是struct对齐大小的整数倍。

4)struct大小计算举例

如:

struct student
{
	char name[5];
	int num;
	short score;
};

name是char型,对齐大小为1字节,num是int型,对齐大小为4字节,score是short型,对齐大小是2字节,所以student的对齐大小是4字节。数据对齐如下图:

|char|char|char|char|

|char|-----|-----|-----|

|----------int----------|

|--short---|-----|-----|

所以sizeof(student)为16。

如果我们把struct中的变量调换一下顺序,就会得到不一样的结果,比如:

struct student
{
	Int num;
	char name[5];
	short score;
};

对齐大小依然为4字节,数据对齐如下图:

|----------int----------|

|char|char|char|char|

|char|-----|--short--|

所以sizeof(student)为12。

5)特殊情况

如果union或者struct为空,则它们的大小都为1。如果union或者struct中有static变量,则在计算大小时忽略掉static变量,因为static变量不属于union或者struct的一部分。例如:

struct str
{
	static int a;
};

计算str大小时,a为static变量,忽略掉。则str相当于一个空的struct,因此sizeof(str)为1。

5.类的大小计算

1)空类

对于一个空类,它的大小为1。

2)简单类

如下定义一个类:

class A
{
public:
	int a;
	char b;
};

对于简单类的大小,与struct一样。所以sizeof(A)为8。同样的,对于static变量也不属于类的一部分,因此计算大小时,要把static变量忽略掉。

3)带虚函数的类

虚函数放在虚表中,类中定义了虚函数,则需要一个指向虚表的指针。例如:

class B
{
public:
	int a;
	virtual void print() { }
};

则sizeof(B)的大小为8。需要注意的是,当有多个虚函数的时候,仍然只需要一个指向虚表的指针,因此,如果类中有多个虚函数,仍然只占一个指针的大小。

6.#pragma pack()命令

为了节省空间,我们可以在编码时通过#pragma pack()命令指定程序的对齐方式,括号中是对齐的字节数,若该命令括号中的内容为空,则为默认对齐方式。例如:

#pragma pack(2) //设置2字节对齐
struct student
{
    char name[5]; //本身1字节对齐,比2字节对齐小,按1字节对齐
    intnum;          //本身4字节对齐,比2字节对齐大,按2字节对齐
    short score;    //本身也2字节对齐,仍然按2字节对齐
};
#pragma pack() //取消设置的字节对齐方式

则student的对齐大小变为2字节,数据对齐如下图:

|char|char|

|char|char|

|char|------|

|-----int-----|

|-----int-----|

|---short---|

所以,sizeof(student)变为12。这样改变默认的字节对齐方式可以更充分地利用存储空间,但是这会降低计算机读写数据的速度,是一种以时间换取空间的方式。

7.笔试题举例

1)2014完美世界笔试填空第11题

class A
{
public:
    A(){}
    virtual ~A(){}
    char m_x;
};
A a;

sizeof(a)的值是:8

解析:虚函数放在虚表中,如果定义了虚函数,则需要存放一个指向虚表的指针。在C++中,指针占4个字节,char类型占1个字节,根据字节对齐的原理,需要占据8个字节,因此类的大小为8。

2)2015腾讯笔试题选择第11题

32位机器上定义如下结构体:

struct xx {
    long long _x1; 
    char _x2; 
    int _x3; 
    char _x4[2]; 
    static int _x5;
 }; 
int xx::_x5;

请问sizeof(xx)的大小是()D

A.19        B.20                C.15             D. 24

解析:_x5位static变量,不占struct的内存空间。_x1对齐大小8个字节,_x2和_x4对齐大小为1个字节,_x3对齐大小为4个字节,所以xx的对齐大小为8字节。字节对齐图如下:

|----------long long----------|

|char|--------|-------int-------|

char|char|--------------------|

所以xx总共会占24个字符。


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值