【牛客题目1】在Visual C++ 和 Mingw64平台上,short a[100], sizeof(a) 返回什么?
A. 2 B. 4 C. 100 D. 200 E. 400
答案:D
Reference: https://www.nowcoder.com/test/question/done?tid=31013888&qid=1490#summary
解析:short int: 2个字节 【1.1】
sizeof 返回的数值表示的含义如下(单位字节)
- 数组 - 编译时分配的数组空间大小 【1.1】(特别地,若数组作为参数被传入函数中做sizeof()运算,则和指针运算没区别)【1.2】
- 指针 - 存储该指针所用的空间大小 (存储该指针的地址长度,是长整型,应该为4) 【2】
- 类型 - 该类型所占用的空间大小 【3】
- 对象 - 对象的实际占用空间大小 【4】
- 函数 - 函数的返回类型所占的空间大小。函数的返回类型不能是void【5】
【题目2-13】
1 char str[] = "Hello"; 2 char *p = str; 3 int n = 10; 4 sizeof(str) = 6; // H,e,l,l,o,\0 [1.1] 5 sizeof(p) = 4; // [2] 6 sizeof(n) = 4; // [3] 7 void Func(char str[10]){ 8 sizeof(str) = 4; // [1.1] 9 } 10 void *p = malloc(100); 11 sizeof(p) = 4; // [2]
【题目2-14】使用sizeof()计算类对象所占空间大小, 结构体和类中的字符串对齐原则
1 #include <iostream> 2 using namespace std; 3 4 class A{ 5 public: 6 int i; //4 7 }; 8 9 class B{ 10 public: 11 char ch; //1 12 }; 13 14 class C{ 15 public: 16 int i; //4+1 ---> 对齐 4+4 = 8 17 short j; 18 }; 19 20 class D{ 21 public: 22 int i; // 4+2+1 ---> 对齐 4+2+1+1 = 8 23 short j; 24 char ch; 25 }; 26 27 class E{ 28 public: 29 int i; // 4+4+2+1+1 = 12 30 int ii; 31 short j; 32 char ch; 33 char chr; 34 }; 35 36 class F{ 37 public: 38 int i; // 4+4+4+2+1+1 = 16 39 int ii; 40 int iii; 41 short j; 42 char ch; 43 char chr; 44 }; 45 46 int main(){ 47 cout<<sizeof(A)<<' '<<sizeof(B)<<' '<<sizeof(C)<<' '<<sizeof(D)<<' '<<sizeof(E)<<' '<<sizeof(F)<<endl; 48 }
答案:4 1 8 8 12 16
为什么要字节对齐?一般情况下,如果不按照适合平台要求对数据存放进行对齐,会给存取效率带来损失。例如,有些平台每次读都是从偶地址开始,如果一个 int 型存放在偶地址开始的地方,那么一个读周期就可以读出;而如果存放在奇地址开始的地方,可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该 int 型数据。显然,在读取效率上下降很多。
字节对齐原则.
(1)结构体变量的首地址能够被其最宽基本类型成员的大小所整除
(2)结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,编译器会在成员之间加上填充字节 (internal adding)
(3)结构体的总大小为结构体最宽基本类型成员大小的整数倍,编译器会在最末一个成员之后填充字节(trailing padding)
【题目2-15】使用 sizeof() 计算含有虚函数的类对象的空间大小
#include <iostream> using namespace std; class Base{ public: Base(int x):a(x){} void print(){cout<<"base:"<<endl;} private: int a; }; class Derived:public Base{ public: Derived(int x):Base(x-1),b(x){} void print(){cout<<"derived"<<endl;} private: int b; }; class A{ public: A(int x):a(x){} virtual void print(){cout<<"A"<<endl;} private: int a; }; class B: public A{ public: B(int x):A(x-1),b(x){} virtual void print(){cout<<"B"<<endl;} private: int b; }; int main(){ Base obj1(1); Derived obj2(2); A obj3(3); B obj4(4); cout<<sizeof(obj1)<<' '<<sizeof(obj2)<<' '<<sizeof(obj3)<<' '<<sizeof(obj4)<<endl; return 0; }
答案: 4 8 8 12
类的普通成员函数不占用内存,只有虚函数占用一个指针大小的内存,原因是系统多用一个指针维护这个类的虚函数表,并且注意这个虚函数无论含有多少项 (类中含有多少个虚函数)都不会再影响类的大小。
【题目2-16】使用sizeof()计算虚拟继承的类对象的空间大小
1 #include<iostream> 2 using namespace std; 3 class A{}; 4 class B{}; 5 class C:public A, public B{}; 6 class D:virtual public A{}; 7 class E:virtual public A,virtual public B{}; 8 class F{ 9 public: 10 int a; 11 static int b; 12 }; 13 int F::b = 10; 14 int main(){ 15 cout<<sizeof(A)<<" "<<sizeof(B)<<" "<<sizeof(C)<<" "<<sizeof(D)<<" "<<sizeof(E)<<" "<<sizeof(F)<<endl; 16 return 0; 17 }
运行结果:1 1 1 4 8 4
Line 3, 4 -> A, B 是空类,编译器会安插一个 char 给空类,用来标记它的每一个对象。因此它的大小为1
Line 5 -> 多类继承,大小为1
Line 6 -> 虚拟继承,编译器为该类安插一个指向父类的指针,编译器不会再安插 char,指针大小为4
Line 7 -> 虚拟继承 A和B, 有指向父类A和父类B的指针,加起来大小为8个字节
Line 8 -> F 含有一个静态成员变量,这个静态成员的空间不在类的实例中,而是像全局变量一样在静态存储区中,被每一个类的实例共享,因此其大小为 4 个字节。
来源:https://www.cnblogs.com/jg01/p/12404743.html