C++面试题(19)| 说出sizeof()的结果

167 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第12天,点击查看活动详情

image.png

(欢迎大家关注我的微信公众号——控制工程研习,上面会分享很多我学习过程中总结的笔记。)

测试

请先思考一下这个程序的结果(32位的系统):


#include <iostream>
using namespace std;

union test {
    double a;
    int b;
    int c[3];
};

int main()
{
    cout << sizeof(test) << endl;

    return 0;
}

答案是16。

如果你答错了,就请看下面的解析吧。

图片

重要特性分析

    sizeof()求结果值在面试中经常会遇到,所涉及的知识点不多,大家应该好好掌握住。最常见的就是求类或结构体的大小,有时甚至还会有联合体的计算。

    我们需要知道sizeof的几个主要特性:

(1)sizeof是一个编译时运算符,而不是函数;

(2)sizeof不能求得void类型的长度,但能求得void类型的指针的长度;

cout << sizeof(void) << endl; // invalid
cout << sizeof(void*) << endl; // valid

(3)sizeof能求得静态分配内存的数组的长度,但不能求得动态分配的内存的大小。

int a[10];
cout << sizeof(a) << endl; // 返回10*sizeof(int)
int * a = new int[10];
cout << sizeof(a) << endl//返回sizeof(int *)

(4)当表达式作为sizeof的操作数时,它返回表达式的计算结果的类型大小,但是它不对表达式求值.

double a;
float b;
cout << sizeof(a+b) << endl; // 返回sizeof(a),这里是由于默认类型转换为double
cout << sizeof(b = a + b) << endl; // 返回sizeof(b),表达式强制转换为了float类型的b

(5)sizeof可以对函数调用求大小,并且求得的大小等于返回类型的大小,但是不执行函数体。


int test_fun()
{
  int ret = 1;
  cout << "in test_fun()" << endl;
  return ret;
}

// ↓ in main function()
cout << sizeof(test_fun()) << endl; // 返回sizeof(int)

(6)sizeof求得的结构体(及其对象)的大小并不等于各个数据成员对象的大小之和。


#include <iostream>
using namespace std;

struct test_str {
  char a;
  int  b;
};

int main()
{
  cout << sizeof(test_str) << endl;
  return 0;
}

这个运行结果可能并不是sizeof(char)+sizeof(int),这个代码会在不同的编译器下得到不一样的结果。原因就是内存对齐,对齐方式为成员中最大成员的对齐方式。

详细内容可以参考(内存对齐的内容还是很重要的):

所以这个结果就是与成员的顺序 和 内存对齐值有关

(7)没有成员变量的结构体/类/联合体的内存值为1。

(8)sizeof(联合体)取决于他所有成员中占用空间最大的一个成员的大小。


#include <iostream>
using namespace std;

union test_union {
  char    a;
  int     b;
  double  c;
};

int main()
{
  cout << sizeof(test_union) << endl;
  return 0;
}

返回结果为sizeof(double)。

练习&测试

    这类在面试中问sizeof()值的题只有记住上面这几个重要特性即可。后面有三个示例,可以自己练习一下(对于32位系统)。

示例一:

#include <iostream>
using namespace std;

#pragma pack(4)
struct test {
    double a;
    int b;
    int c[2];
};

int main()
{
    cout << sizeof(test) << endl;

    return 0;
}

答案:

24

sizeof(double) = 8,sizeof(int) =4。这里内存对齐值是8,所以b占用内存还是8。c数组也占用8。

图片

示例二:

#include <iostream>
using namespace std;

#pragma pack(4)
struct test {
    double a;
    int b;
    int c[2];
};

int main()
{
    cout << sizeof(test) << endl;

    return 0;
}

答案:

20.

    这里使用#pragma pack(4)修改了内存对齐值为4。所以内存情况如下:

图片

示例三(一开始的测试题):


#include <iostream>
using namespace std;

union test {
    double a;
    int b;
    int c[3];
};

int main()
{
    cout << sizeof(test) << endl;

    return 0;
}

答案:

16.

    这里首先需要知道sizeof(union)返回成员中最大内存的值,也就是sizeof(c)了,这里的c数组大小为3,且为int类型,可能有人就计算其为12了。这没有考虑这个数组在这个联合体中内存对齐的问题,其对齐值是8。所以sizeof(c)的结果就是16了。所以这类题要细心。