中级C++开发人员的棘手面试问题

Tricky interview question for mid-level C++ developer

本文关键字:面试 问题 C++ 开发 中级      更新时间:2023-10-16

我在面试中被问到这个问题,我真的不明白这里发生了什么。问题是"控制台中将显示什么?

#include <iostream>
int main()
{
unsigned long long n = 0;
((char*)&n)[sizeof(unsigned long long)-1] = 0xFF;
n >>= 7*8;
std::cout << n;
}

这里正在一步一步地发生什么?

让我们一步一步地了解这一点:

((char*)&n)

这会将变量n的地址从unsigned long long*转换为char*。这是合法的,实际上通过char指针访问不同类型的对象是该语言接受的极少数"类型双关"情况之一。这实际上允许您以字节数组(也称为charC++)的形式访问对象n的内存

((char*)&n)[sizeof(unsigned long long)-1]

访问对象的最后一个字节n。请记住,sizeof返回数据类型的维度(以字节为单位)(以字节为单位C++char具有字节的另一个自我)

((char*)&n)[sizeof(unsigned long long)-1] = 0xFF;

n的最后一个字节设置为值0xFF

由于n最初0n的布局记忆是:

00  .. 00 FF

现在注意我放在中间的...。这不是因为我懒得复制粘贴n的字节数,而是因为标准没有将unsigned long long的大小设置为固定维度。有一些限制,但可能因实现而异。所以这是第一个"未知"。然而,在大多数现代架构上,sizeof (unsigned long long)是 8,所以我们打算这样做,但在严肃的采访中,你应该提到这一点。

另一个"未知"是如何解释这些字节的。无符号整数只是以二进制编码。但它可以是小端序或大端序。x86 是小端序,所以我们用它作为示例。再一次,在严肃的采访中,你应该提到这一点。

n >>= 7*8;

这个权利将n的值移动了56倍。注意,现在我们谈论的是n的值,而不是内存中的字节。根据我们的假设(大小 8,小端序),内存中编码的值是0xFF000000 00000000因此将其移动7*8次将导致值0xFF,即255

因此,假设sizeof(unsigned long long)8并且程序的小端序编码255打印到控制台。


如果我们谈论的是大端系统,将最后一个字节设置为0xff后的内存布局仍然相同:00 ... 00 FF,但现在编码的值是0xFF.所以n >>= 7*8;的结果将是0.在大端系统中,程序会将0打印到控制台。


正如评论中指出的,还有其他假设:

  • char是 8 位。虽然sizeof(char)保证是1的,但它不必有8位。我所知道的所有现代系统都有以 8 位字节分组的位。

  • 整数不必是小端或大端。可以有其他排列模式,如中端序。如今,除了小端或大端之外的东西被认为是深奥的。

n的地址转换为指向 chars 的指针,将第 7 个(假设 sizeof(long long)==8) char 元素设置为 0xff,然后将结果(作为长 long)右移 56 位。