【牛客题目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