sizeof 是一个关键字、操作符,也是一个编译时运算符
作用:返回一个对象或者类型所占的内存字节数
sizeof(type_name);//sizeof(类型)
sizeof(object);//sizeof(对象)
注意:
sizeof 操作符不能用于函数类型,不完全类型或位字段
不完全类型:指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void 类型……
sizeof(void)
不是正确形式
本质:将对象转换成对象类型进行计算,同种类型的不同对象其 sizeof 值相同
常见字长:
#include
#include
using namespace std;
int main() {
cout << "sizeof(bool)=" << sizeof(bool) << endl; // 1
cout << "sizeof(char)=" << sizeof(char) << endl; // 1
cout << "sizeof(short)=" << sizeof(short int) << endl; // 2
cout << "sizeof(int)=" << sizeof(int) << endl; // 4
cout << "sizeof(long)=" << sizeof(long int) << endl; // 4
cout << "sizeof(long long)=" << sizeof(long long) << endl; // 8
cout << "sizeof(float)=" << sizeof(float) << endl; // 4
cout << "sizeof(double)=" << sizeof(double) << endl; // 8
return 0;
}
编译器根据表达式的最终结果类型确定大小,sizeof 是编译时进行计算,与运行时无关,不会对表达式进行计算
#include
#include
using namespace std;
int main() {
int i = 8;
cout << "sizeof(i)=" << sizeof(i) << endl; // 4
cout << "sizeof(i=5)=" << sizeof(i = 5) << endl; // 4
cout << i << endl;//sizeof(i = 5)不会改变i的值
cout << "sizeof(i++)=" << sizeof(i++) << endl; // 4
cout << i << endl;//sizeof(i++)不会改变i的值
return 0;
}
指针变量的 sizeof 值与指针所指的对象类型无关,与指针申请的空间大小无关,所有指针变量所占内存大小均相等
32 位系统中,返回 4;64 位系统中,返回 8
#include
using namespace std;
char fun() {
return 'c';
}
int main() {
//指向char类型变量的指针
char c;
char* ptr_char = &c;
cout << "sizeof(ptr_char) = " << sizeof(ptr_char) << endl; // 8
//指向int类型变量的指针
int i;
int* ptr_int = &i;
cout << "sizeof(ptr_int) = " << sizeof(ptr_int) << endl; // 8
//指向double类型变量的指针
double* ptr_double = new double[10];
cout << "sizeof(ptr_double) = " << sizeof(ptr_double) << endl; // 8
//二级指针
char** two_ptr_char = &ptr_char;
cout << "sizeof(二级指针) = " << sizeof(two_ptr_char) << endl; // 8
//函数指针:指向函数的指针,指针函数:返回值是指针的函数
void (*ptr_f)();
cout << "sizeof(函数指针) = " << sizeof(ptr_f) << endl; // 8
//&fun:一个函数指针
cout << "sizeof(&fun) = " << sizeof(&fun) << endl; // 8
//fun():一次函数调用
cout << "sizeof(fun()) = " << sizeof(fun()) << endl;// 1,返回返回值的类型的大小
//(*fun)():一次函数调用
cout << "sizeof((*fun)()) = " << sizeof((*fun)()) << endl;// 1,返回返回值的类型的大小
return 0;
}
数组所有元素所占用的大小
#include
using namespace std;
void foo(int a[3]) {//当数组作为函数形参时,以指针类型进行传递
cout << "sizeof(a) = " << sizeof(a) << endl; // 8,a以指针传递,故a为指针
}
int main() {
//二维数组
int A[3][5];
cout << "sizeof(A) = " << sizeof(A) << endl; // 60=3*5*4,A的数据类型为int[3][5]
cout << "sizeof(A[0]) = " << sizeof(A[0]) << endl; // 20=5*4,A[0]的数据类型为int[5]
cout << "sizeof(A[4]) = " << sizeof(A[4]) << endl; // 20=5*4,A[4]的数据类型为int[5]
//虽然A[4]下标越界,但sizeof只关心数据类型,在编译阶段已经完成,不会造成运行错误
cout << "sizeof(A[0][0]) = " << sizeof(A[0][0]) << endl; // 4=1*4,A[0][0]的数据类型为int
cout << "sizeof(A[0][1]) = " << sizeof(A[0][1]) << endl; // 4=1*4,A[0][1]的数据类型为int
//字符串
char c[] = "abcdef";
cout << "sizeof(c) = " << sizeof(c) << endl; // 7=6+1('\0')
//指针数组=指针内存大小*元素个数
char* ch[10];
cout << "sizeof(ch) = " << sizeof(ch) << endl; // 80,ch是一个数组,数组的元素是指针
cout << "sizeof(*ch) = " << sizeof(*ch) << endl; // 8,*ch是一个指针,是数组的第一个元素
cout << "sizeof(**ch) = " << sizeof(**ch) << endl; // 1,**ch是一个char变量,是数组的第一个元素(指针)指向的变量
//数组指针
int* (*d)[3][6];
cout << "sizeof(d) = " << sizeof(d) << endl; // 8,d是一个指针,指向一个二维数组,二维数组的元素是int类型的指针
cout << "sizeof(*d) = " << sizeof(*d) << endl; // 144=3*6*8,*d是一个二维数组,是d指向的二维数组
cout << "sizeof(**d) = " << sizeof(**d) << endl; // 48=6*8,**d是一个一维数组
cout << "sizeof(***d) = " << sizeof(***d) << endl; // 8,***d是一个指针
cout << "sizeof(****d) = " << sizeof(****d) << endl; // 4,****d是一个int变量
//一维数组
int nums[] = { 1,2,3 };
cout << "sizeof(nums) = " << sizeof(nums) << endl; // 12=3*4
foo(nums);//参数以指针传递
return 0;
}
#include
#include
#include
using namespace std;
int main() {
const char* strPtr = "hyy";
char strs[] = "hyy";
string str = "h";
cout << "sizeof(strPtr) = " << sizeof(strPtr) << endl; // 8,strPtr是一个指针
cout << "sizeof(strs) = " << sizeof(strs) << endl; // 4,strs是一个字符数组,包括 '\0'
cout << "sizeof(str) = " << sizeof(str) << endl; // 40,str是一个string类对象,是string类所占的实际内存
cout << "sizeof(string) = " << sizeof(string) << endl; // 40
cout << "strlen(strPtr) = " << strlen(strPtr) << endl; // 3
cout << "strlen(strs) = " << strlen(strs) << endl; // 3
cout << "str.size() = " << str.size() << endl; // 1
return 0;
}
返回函数返回值类型的大小,函数并不会被调用执行
sizeof(函数名(实参表))
PS:
#include
using namespace std;
int intfun() {
return 1;
}
double doufun(int a, double b) {
return a + b;
}
void voidfun() { }
int main() {
// cout << "sizeof(intfun) = " << sizeof(intfun) << endl; //编译失败
cout << "sizeof(intfun()) = " << sizeof(intfun()) << endl; // 4
cout << "sizeof(doufun(1, 1.5)) = " << sizeof(doufun(1, 1.5)) << endl; // 8,不可省略实参列表
// cout << "sizeof(voidfun()) = " << sizeof(voidfun()) << endl; //编译失败
return 0;
}
内存对齐
对其目的:减少访存指令周期,提高 CPU 存储速度
一般情况下,结构体所占内存大小并非元素本身大小之和
#include
using namespace std;
struct S1 {
char c;
int i;
};
int main() {
cout << "sizeof(S1) = " << sizeof(S1) << endl; // 8
return 0;
}
// sizeof(S1) =/= sizeof(char) + sizeof(int)
结构体或类成员变量具有不同类型时,需进行成员变量的对齐
每个特定平台上的编译器都有自己的默认“对齐系数”(对齐模数)
32 位机对齐(默认)是按4字节对齐,而 64 位机(默认)是按8字节对齐
模数在不同平台值不同,可使用#pragmapack(n)
改变
对其原则:
空结构体(不含数据成员)的 sizeof 值为 1
静态成员存放在静态存储区,不占用结构体的大小
成员函数不占用结构体的大小
#include
using namespace std;
struct st0 {
char a; // 1 + pad(7)
char* a1; // 8
int c; // 4 + pad(4)
}; // 24
//a 的长度为 1,所占的地址为 0;
//a1 的长度为 8,偏移前的首地址为 1,因为首地址不是成员大小的整数倍,故需偏移,使其首地址为 8 即可,故加上 7 个填充字节;
//c 的长度为 4,首地址为 16,结构体的大小为 20,不是最宽基本成员(8)的整数倍,故需填充 4 个字节,使得结构体总大小为 24
struct st1 {
char a; // 1 + pad(7)
double b; // 8
int c; // 4
char d; // 1 + pad(3)
}; // 24
// a 的长度为 1,所占的地址为 0;
// b 的长度为 8,偏移前的首地址为 1,因为首地址不是成员大小的整数倍,故需偏移,使其首地址为 8 即可,故加上 7 个填充字节;
// c 的长度为 4,首地址为 16
// d 的长度为 1,首地址为 20,结构体大小为 21,不是最宽基本成员(8)的整数倍,故需填充 3 个字节,使得结构体总大小为 24
struct st2 {
char a; // 1
char a1; // 1 + pad(2)
int c; // 4
st1 st; // 24
char d; // 1 + aad(7)
}; // 40
// a 的长度为 1,所占的地址为 0;
// a1 的长度为 1,所占的地址为 1,首地址是成员大小的整数倍,故不需要偏移
// c 的长度为 4,偏移前的首地址为 2,因为首地址不是成员大小的整数倍,故需偏移,使其首地址为 4 即可,故加上 2 个填充字节;
// st 的长度为 24,首地址为 8,虽然首地址不是成员大小的整数倍,但因为成员大小超过默认模数,故以模数进行对齐
// d 的长度为 1,首地址为 32,结构体大小为 33,不是模数(8)的整数倍(因为最宽基本成员类型大小超过模数,故以模数进行对齐),故需填充 7 个字节,使得结构体总大小为 40
int main() {
cout << "sizeof(st0) = " << sizeof(st0) << endl; // 24
// 获取成员在结构体的地址偏移量
cout << "offsetof(st0, a) = " << offsetof(st0, a) << endl; // 0
cout << "offsetof(st0, a1) = " << offsetof(st0, a1) << endl; // 8
cout << "offsetof(st0, c) = " << offsetof(st0, c) << endl; // 16
cout << "sizeof(st1) = " << sizeof(st1) << endl; // 24
cout << "offsetof(st1, a) = " << offsetof(st1, a) << endl; // 0
cout << "offsetof(st1, b) = " << offsetof(st1, b) << endl; // 8
cout << "offsetof(st1, c) = " << offsetof(st1, c) << endl; // 16
cout << "offsetof(st1, d) = " << offsetof(st1, d) << endl; // 20
cout << "sizeof(st2) = " << sizeof(st2) << endl; // 40
cout << "offsetof(st2, a) = " << offsetof(st2, a) << endl; // 0
cout << "offsetof(st2, a1) = " << offsetof(st2, a1) << endl; // 1
cout << "offsetof(st2, c) = " << offsetof(st2, c) << endl; // 4
cout << "offsetof(st2, st) = " << offsetof(st2, st) << endl; // 8
cout << "offsetof(st2, d) = " << offsetof(st2, d) << endl; // 32
return 0;
}
进行 sizeof 计算时,类与结构体类似
#include
using namespace std;
class c0 {
char a; // 1 + pad(7)
char* a1; // 8
int c; // 4 + pad(4)
}; // 24
class c1 {
char a; // 1 + pad(7)
double b; // 8
int c; // 4
char d; // 1 + pad(3)
}; // 24
class c2 {
char a; // 1
char a1; // 1 + pad(2)
int c; // 4
c1 cla; // 24
char d; // 1 + pad(7)
}; // 40
struct c3
{
static int i; // 静态成员
int fun(); // 成员函数
int d; // 4
char ch; // 1 + pad(3)
virtual int vir1(); // 8 (64bit)
}; // 16
class A{}; // 1,空类
class B {
virtual int fun(){ // 虚函数
return 0;
}
}; // 8
class C {
static int a; // 静态成员
void fun(); // 成员函数
}; // 1
int main() {
cout << "sizeof(c0) = " << sizeof(c0) << endl; // 24
cout << "sizeof(c1) = " << sizeof(c1) << endl; // 24
cout << "sizeof(c2) = " << sizeof(c2) << endl; // 40
cout << "sizeof(c3) = " << sizeof(c3) << endl; // 16
cout << "sizeof(A) = " << sizeof(A) << endl; // 1
A a;
cout << "sizeof(a) = " << sizeof(a) << endl; // 1,空类的实例大小就是类的大小
cout << "sizeof(B) = " << sizeof(B) << endl; // 8
B b;
cout << "sizeof(b) = " << sizeof(b) << endl; // 8
cout << "sizeof(C) = " << sizeof(C) << endl; // 1
C c;
cout << "sizeof(c) = " << sizeof(c) << endl; // 1
return 0;
}
sizeof(string)
计算 string 变量在内存中的空间大小,与字符串长度无关
string 在内存中的布局:
sizeof(vector)
计算 vector 变量在内存中的空间大小,与变量中元素的个数无关
结构体在内存组织上是顺序式的,联合体是重叠式,各成员共享一段内存,所以整个联合体的 sizeof 就是每个成员 sizeof 的最大值
#include
using namespace std;
class c {
char a; // 1 + pad(7)
char* a1; // 8
int c; // 4 + pad(4)
}; // 24
union U {
int i; // 4
char c; // 1
class c c_c;// 24
};
int main() {
cout << "sizeof(U) = " << sizeof(U) << endl; // 24
return 0;
}