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

时间:2019-07-20 01:45:48

标签: c++

面试中有人问我这个问题,我真的不明白这里发生了什么。问题是“控制台中将显示什么?”

#include <iostream>

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

    n >>= 7*8;

    std::cout << n;
}

这里正在逐步发生什么事情?

2 个答案:

答案 0 :(得分:50)

让我们一次做到这一步:

((char*)&n)

这会将变量n的地址从unsigned long long*强制转换为char*。这是合法的,实际上通过char指针访问不同类型的对象是该语言接受的少数“类型调整”情况之一。实际上,这使您可以将对象n的内存作为字节数组(在C ++中也称为char)访问

((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,因此我们将继续讨论这个问题,但是在认真的采访中,您应该提到这一点。

另一个“未知”是如何解释这些字节。无符号整数只是简单地以二进制编码。但是可以是little endian or big endian。 x86的字节序不大,因此我们以它为例进行说明。再一次,在认真的采访中,您应该提到这一点。

n >>= 7*8;

此右移n的值56次。请注意,现在我们谈论的是n的值,而不是内存中的字节。根据我们的假设(大小8,低字节序),在内存中编码的值为0xFF000000 00000000,因此将其移位7*8次将得到值为0xFF的{​​{1}}。

因此,假设255sizeof(unsigned long long),并且对程序进行了一点字节序编码,就会将8打印到控制台。


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


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

  • 0为8位。尽管保证charsizeof(char),但它不必具有8位。我所知道的所有现代系统都有以8位字节分组的位。

  • 整数不必大或小。可能还有其他排列方式,例如middle endian。如今,除了大尾数之外,其他东西都被认为是深奥的。

答案 1 :(得分:4)

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