sizeof运算符使用注意事项


一    C++内置类型所占字节数

32位编译器

类型所占字节
bool1
char1
short2
int4
unsigned4
long4
unsigned long4
long long8
float4
double8
long double 8
char * (指针) 4

note

  • 无符号类型与有符号类型所占字节数相同
  • 64位编译器:指针类型所占字节数为8,long double 在vs2017-64位编译器下占8字节,在clion-64编译器中为16, 不同平台所占字节数不同,较为少用。其它数据类型与32位编译器相同

最好自己实践一波:

    std::cout << "bool :\t" << sizeof(bool) << std::endl;
    std::cout << "char :\t" << sizeof(char) << std::endl;
    std::cout << "short :\t" << sizeof(short) << std::endl;
    std::cout << "int :\t" << sizeof(int) << std::endl;
    std::cout << "long :\t" << sizeof(long) << std::endl;
    std::cout << "long long :\t" << sizeof(long long) << std::endl;
    std::cout << "float :\t" << sizeof(float) << std::endl;
    std::cout << "double :\t" << sizeof(double) << std::endl;
    std::cout << "long double :\t" << sizeof(long double) << std::endl;
    std::cout << "char * :\t" << sizeof(char *) << std::endl;
    std::cout << "unsigned :\t" << sizeof(unsigned) << std::endl;
    std::cout << "unsigned long :\t" << sizeof(unsigned long) << std::endl;


二    用户自定义数据类型

1.   联合体的sizeof

联合体各成员共享一段内存;所以整个联合体的sizeof也就是每个成员sizeof的最大值。但是也会有字节对齐,按照最大内置数据类型的字节数对齐。


-----以下所有用例在32位,64位编译器下亲测,结果一致----

例1:

union u  
{  
    int a;  
    float b;  
    double c;  
    char d[17];  
};

最大数据类型为double,8字节。最大数据成员是d,占17字节,但是按照8字节对齐。联合体占内存大小:17 + 7 = 24(字节)

测试结果:24


例2:对比上例

union u  
{  
    int a;  
    float b;  
    char c[17];  
};

最大数据类型为int,4字节。最大数据成员是c,占17字节,但是按照4字节对齐。联合体占内存大小:17 + 3 = 20(字节)

测试结果:20

2.   结构体的sizeof

C++结构体字节对齐:
计算机系统对基本类型数据在内存中存放的位置有限制,要求这些数据的起始地址的值是某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。

对齐规则(个人总结):

  1. 先寻找结构体中最大的数据类型;
  2. 每个结构体成员按最大数据类型所占的字节数分配内存,如果相邻的几个数据成员所需要的内存之和,少于一个最大数据类型所占的内存,则共用一个单位(最大数据类型)的内存空间。

例1:

struct MyStruct
{
    char a;
    int b;
    double c;
};

最大数据类型为double,8字节。所以a分配8字节,剩余7字节。b与a相邻,b只需要4字节,可以存放在a中,所以b不必分配新内存,a,b共占8字节。c占8字节。结构体占内存大小:8+8 = 16(字节)

测试结果:16


例2:

struct MyStruct
{
    char a;
    double b;
    char c;
};

最大数据类型为double,8字节。所以a分配8字节,剩余7字节,不足以存下b,所以b重新分配8字节。同理,c也占8字节。结构体占内存大小:8+8+8 = 24(字节)

测试结果:24


例3:空结构体

struct MyStruct
{
   
};

空结构体,在C语言中占0字节,在C++中占1字节。

测试结果:1


例4:结构体有静态成员

struct MyStruct
{
    char a;  
    int b;  
    static double c; //静态成员
};

静态成员变量存放在全局数据区内,在编译的时候已经分配好内存空间,所以对结构体的总内存大小不做任何贡献;结构体占内存大小:4+4 = 8(字节)

测试结果:8


例5:结构体中包含结构体

struct E{  
    int a;  
    double b;  
    float c;  
}; 

struct MyStruct
{
    char a;  
    int b;  
    struct E c; //结构体成员
};

结构体E中最大数据类型是sizeof(double)=8,且sizeof(E)=8+8+8=24个字节;在结构体MyStruct中,最大数据类型取E的最数据类型8;a,b共占8字节。结构体占内存大小:8+24 = 32(字节)

测试结果:32


例6:结构体中包联合体

union U
{
    int a;
    double b;
    char c[17];
};

struct MyStruct
{
    char a;  
    int b;  
    union U c; 
};

联合体U中最大数据类型是sizeof(double)=8,且sizeof(U)=17 + 7=24个字节;在结构体MyStruct中,最大数据类型取U的最大数据类型double;a,b共占8字节。结构体占内存大小:8+24 = 32(字节)

测试结果:32


例7:结构体中包数组

struct MyStruct
{
    char a;  
    int b;  
    char c[5]; 
};

结构体中最大数据类型是sizeof(int)=4,所以c必须按4字节对齐。结构体占内存大小:4+4+5+3 = 16(字节)

测试结果:16

C++ #pragma pack宏的对齐
#pragma pack (n) //编译器将按照n个字节对齐
#pragma pack () //取消自定义字节对齐方式

3.   数组的sizeof

note

  • 当字符数组表示字符串时,其sizeof值将’/0’计算进去
  • 当数组为形参时,其sizeof值相当于指针的大小

例1:

char a[10];  
char n[] = "abc";

测试结果:sizeof(a) = 10,sizeof(n) = 4


例2:函数传参为数组

int func(char a[])  
{  
   return sizeof(a);   
}  
Clion编译期间警告:warning: 'sizeof' on array function parameter 'a' will return size of 'char*'

测试结果:32位:sizeof(a) = 4,64位:sizeof(a) = 8


例3:sizeof求整形数组的长度!!!!!!!

    int arr[] = {5,7,6,9,11,10,8};
    cout << "The length of arr: " << sizeof(arr) / sizeof(int) << endl;		//	输出7

	int *A = new int[10];
	cout << sizeof(A) << endl;  //	输出4, A是指针,属于动态分配

数组名不完全等同于指针:

int intArray[10];
intArray++	//	编译出错,数组名可以被看作一个指针常量,不能被修改。

但是,数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针。失去了其常量特性,可以作自增、自减等操作,可以被修改。

4.   函数的sizeof

sizeof对一个函数调用,其结果是函数返回值类型的大小,函数并不会被报执行。

note

  • 不可以对返回值类型为空的函数求值
  • 不可以对函数名求值
  • 对有参数的函数,在用sizeof时,须写上实参表

例1:

int func1(int a, int b)  
{  
    return a + b;  
}  
  
int func2()  
{  
    return 3;  
}  
  
void func3()  
{
  
}  

测试结果:sizeof( func1(1,2) ) = sizeof( int ) = 4;
                  sizeof( func2() ) = sizeof( int ) = 4;
                  sizeof( func3() ) == 编译出错

5.   类的sizeof

与结构体的sizeof相似,类的函数不占空间,成员变量占空间,但如果包含虚函数,则类会默认包含一个虚函数表指针,无论虚函数有多少个,类的大小只会增加一个指针大小。

举例:

#include <iostream>
using namespace std;

class Base
{
    public:
       Base() { }
       virtual void print1() = 0;
       virtual void print2() = 0;
       virtual void print3() = 0;
 
    private:
        int* m_pNum;
};

int main()
{
   cout << sizeof(Base) << endl;
}

64位机器输出结果:

16


参考:
https://www.cnblogs.com/huolong-blog/p/7587711.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值