C++:sizeof() —— 变量、指针、数组、类、结构体、联合体(共用体)、枚举类型

一、基本计算

1、变量大小(64位机)

sizeof(bool) = 1

sizeof(char) = 1

sizeof(short) = 2

sizeof(int) = 4

sizeof(long) = 4

sizeof(long long) = 8

sizeof(float) = 4

sizeof(double) = 8

2、数组、指针大小

char arr[10];

char str[] = "hello world";

char *p = "hello world";



sizeof(arr) = 10

sizeof(str) = 12

sizeof(p) = 4               // 指针变量的大小

3、类、结构体

        字节对齐:(1)对齐最宽的成员;(2)类/结构体的大小是最宽成员宽度的整数倍。

class A {
	char a;
};

class B {
	char a;
	int b;
};

class C {
	char a;
	int b;
	short c;
};

class D {
	char a;
	int b;
	short c;
	char *p;
};

class E {
	char a;
	int b;
	short c;
	char *p;            // 指针占 4 个字节
	double d;
};

class F {
	char a;
	short b;
	short c;
};

class G {
	char a[11];            // 2 字节对齐,后面补 1 个空位,占 12 个字节
	short b;
	short c;
};



sizeof(A) = 1              // 1字节对齐

sizeof(B) = 8              // 4字节对齐

sizeof(C) = 12             // 4字节对齐

sizeof(D) = 16             // 4字节对齐

sizeof(E) = 24             // 8字节对齐

sizeof(F) = 6              // 2字节对齐

sizeof(G) = 16             // 2字节对齐

4、联合体(共用体)

        联合体的大小:最宽成员大小的整数倍。

        特点:只能给一个成员赋值,所有成员共享一块内存。

union A {
	char a;
};

union B {
	char a;
	short b;
};

union C {
	char a;
	short b;
	int c;
};

union C {
	char a[10];
	short b;
	int c;
};

union D {
	char a[10];           // 最大 10,不是 4 的倍数,改 12
	short b;
	int c = 10;
};



sizeof(A) = 1             // 最宽成员大小 1

sizeof(B) = 2             // 最宽成员大小 2

sizeof(C) = 4             // 最宽成员大小 4

sizeof(D) = 12            // 最宽成员大小的整数倍 4*3,也是一种对齐


    所有成员共享一块内存:
    cout << (int)(aa.a[0]) << endl;            10
    cout << (int)(aa.a[1]) << endl;            0
    cout << aa.b << endl;                      10
    cout << aa.c << endl;                      10

5、枚举类型

        枚举类型的大小:4个字节

        特点:保存一个从0开始的序列。

                   对于成员,是枚举常量,值为序列号,不能再被赋值;

                   成员就像宏常量一样,可以用来给枚举变量赋值,也可以用来给其他对象赋值。局部变量会屏蔽枚举常量。

                   对于枚举变量/对象,其值只能赋值为其成员,不能直接赋值为 0, 1, 2, ...。不能用枚举变量引用其成员。

union A {
	a
};

union B {
	a,
	b,
	c,
	d,
	e,
	f
};



sizeof(A) = 4

sizeof(B) = 4

6、位段结构体

        位段结构体大小:最宽成员的大小的整数倍。

        位域/位段:以位为单位来指定成员所占内存的长度,这种成员称为“位域”或“位段”。

        特点:

        (1)成员类型 —— long long、int、short、char(unsigned char)。有符号或者无符号类型。char 默认是无符号的。

        (2)一个位域必须存储在同一个存储单元中,不能跨越两个存储单元。

        (3)存储单元的大小是最宽成员的宽度。

        (4)位域长度不能大于存储单元的长度,不能定义位域数组。

        (5)通过使用空域,可以使下一个位域从下一个存储单元开始存放。

struct A {
	int a:8;
	int b:2;
	int c:6;
};

struct B {
	int a : 8;
	int b : 2;
	int : 0;               // 空域,使下一个位域从下一个存储单元 (int) 开始存放
	int d : 3;
};

struct C {
	short a : 8;
	short b : 2;
	short : 0;
	short d : 3;
};

struct D {
	short a : 8;
	short b : 2;
	short : 0;
	int d : 3;
};

struct E {
	int a : 8;
	short b : 2;
	short : 0;
	short d : 3;
};

sizeof(A) = 4              // 1 * int

sizeof(B) = 8              // 2 * int

sizeof(C) = 4              // 2 * short

sizeof(D) = 8              // 2 * int

sizeof(E) = 8              // 2 * int

二、复杂分析

1、结论

(1)无论是结构体,还是联合体,对齐方式都是一样的 —— 与最宽基本类型对齐。

(2)结构体取和,联合体取最大。

(3)嵌套的情况,必须定义子对象才有意义,否则无大小无意义。

(4)嵌套时,与最宽基本类型对齐。

2、嵌套计算

(1)先确定计算子对象大小,并将其转化为等效对象

(2)再计算

3、案列分析

(1)按 4 字节对齐,填充内存

class class_abc {
	int a;        // 4
	char b[10];   // 12
};

// --- 与4对齐 ---

4    //a
4    //b
4
2

(2)按 4 字节对齐,取最大的

union union_abc {
	int a;        // 4,与4对齐
	char b[10];   // 12
};


// --- 与4对齐 ---

4
4
2

(3)按 4 字节对齐,填充内存

class class_abcdef {
	int a;                   // 2,与2对齐
	char b[9];                // 9
	short c[3];               // 6
	char d[5];                // 5
};

// --- 与4对齐 ---

4     //a
4     //b
4
1 2   //b,c
4
4     //d
1

(4)内层按 4 字节对齐,等效为 int c[3],外层按等效后的 4 字节对齐

class class_abcdef {
	int a;                   // 4,与2对齐
	char b[9];                // 9

	union union_abcdef {       // 与4对齐,12,相当于 int c[3];
		int a;
		char b[10];
	} abcdef;           // 注意,不定义对象的话,该块大小按 0 计算  !!!
};

// --- 与4对齐 ---

4     //a
4     //b
4
1 
4     //c
4 
4

(5)内层按 1 字节对齐,等效为 char c[10],外层按等效后的 4 字节对齐

class class_abcdef {
	int a;                   // 4,与2对齐
	char b[9];                // 9

	union union_abcdef {       // 与1对齐,10,相当于 char c[10];
		char b[10];
	} abcdef;           // 注意,不定义对象的话,该块大小按 0 计算  !!!
};

// --- 与4对齐 ---

4     //a
4     //b
4
1 3   //b,c
4
3

(6)内层按 1 字节对齐,等效为 char c[10],外层按等效后的 4 字节对齐

class class_abcdef {
	int a;                   // 4,与2对齐
	char b[9];                // 9

	union union_abcdef {       // 与1对齐,10,相当于 char c[10];
		char b[10];
	} abcdef;           // 注意,不定义对象的话,该块大小按 0 计算  !!!

	char d;
};

// --- 与4对齐 ---

4     //a
4     //b
4
1 3   //b,c
4
3 1   //c,d

(7)内层按 8 字节对齐,等效为 double c[2],外层按等效后的 8 字节对齐

class class_abcdef {
	int a;                   // 4,与2对齐
	char b[9];                // 9

	union union_abcdef {       // 与8对齐,16,相当于 double c[2];
		double a;
		char b[10];
	} abcdef;           // 注意,不定义对象的话,该块大小按 0 计算  !!!

	char k;
};

// --- 与8对齐 ---

4 4   //a,b
5     //b
8     //c
8
1     //d

(8)内层按 4 字节对齐,等效为 int c[3],外层按 8 字节对齐

class class_abcdef {
	double a;                   // 4,与2对齐
	char b[9];                // 9

	union union_abcdef {       // 与4对齐,12,相当于 int c[3];
		int a;
		char b[10];
	} abcdef;           // 注意,不定义对象的话,该块大小按 0 计算  !!!

	char k;
};

// --- 与8对齐 ---

8     //a
8     //b
1 4   //b,c
8
1     //d

 

 

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C 语言指针是一种数据型,它存储着一个变量的地址。通过指针,我们可以直接访问存储在该地址上的值,而不是访问变量本身。指针数组结构体有广泛的应用。 在数组数组名本身就是一个指向数组第一个元素的指针。我们可以通过指针来遍历数组的元素,也可以通过指针来进行数组元素的赋值和访问。例如,下面的代码创建了一个整型数组及其指针,并通过指针访问了数组的元素: ``` int array[5] = {1, 2, 3, 4, 5}; int *p = array; // p 指向数组第一个元素 for (int i = 0; i < 5; i++) { printf("%d ", *(p + i)); // 通过指针访问数组元素 } ``` 在结构体指针可以用来访问结构体成员和动态分配内存。例如,下面的代码创建了一个包含两个成员(整型和字符指针)的结构体,并通过指针访问了结构体成员: ``` struct mystruct { int num; char *string; }; struct mystruct data = {10, "hello world"}; struct mystruct *p = &data; // p 指向结构体变量 data printf("%d %s\n", p->num, p->string); // 通过指针访问结构体成员 ``` 指针还可以用来动态分配内存。例如,下面的代码使用指针动态分配了一个整型数组: ``` int *p = malloc(5 * sizeof(int)); // 动态分配 5 个整型空间 p[0] = 1; // 访问第一个元素 free(p); // 释放动态分配的内存 ``` 总之,指针是 C 语言非常重要的概念,掌握指针的使用对于编写高效、灵活的代码非常有帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值