面试问题

昨天我在采访中被问到了下面代码的输出

#include <stdio.h> int main(void){ printf ("%x" ,-1<<4); } 

我被给了2分钟来说出答案。 我回应了fffffff0 。 采访的结果还没有被宣布。 我想知道我的答案是否正确?

技术上左移一个负整数将调用未定义的行为。 这意味着-1<<4是UB。 我不知道他们为什么问你这个问题。 可能他们想testing你对C和C ++标准的深入了解。

C99 [ 6.5.7/4 ]说

E1 << E2的结果是E1左移E2位的位置; 空位填充零。 如果E1具有无符号types,则结果的值是E1×2 E2 ,比结果types中可表示的最大值减1。 如果E1具有带符号的types和非负值,并且在结果types中可以表示E1×2 E2 ,那么这是结果值; 否则,行为是不确定的

C ++ 03通过省略相关的文本使其不明确的行为。

不,你不对。 这是个坏消息。 好消息是,面试官可能不知道,并会认为你是因为这是他们编译和运行的结果。

真正的答案是它是实现定义的。 我不是100%自信地说这是因为超负荷而未定义的行为,但我认为可能是。 至less结果取决于如何表示负数,等等……你所声称的这两种语言都不是定义输出的结果。

在我的机器上:

 chris@zack:~$ cat > test.c #include <stdio.h> int main(void){ printf ("%x" ,-1<<4); } chris@zack:~$ gcc -o test test.c && ./test fffffff0 

但是,结果将取决于您的体系结构和编译器。 所以正确的答案是“它可以输出任何东西”。

 Binary of 1 : 0000 0000 0000 0000 0000 0000 0000 00001 

用你想要计算负号的二进制数来replace0的出现次数

如何计算负数的二进制数

 Binary of -1 : 1111 1111 1111 1111 1111 1111 1111 11111 Left shift 4 : 1111 1111 1111 1111 1111 1111 1111 0000 

结果左移4的hex表示

 1111 : F 0000 : 0 

所以计算的输出将是:

 FFFFFFF0 

你的回答是对的。

左移一个负数对于一般情况是不确定的,但是我们必须理解为什么这个未定义的行为(UB)? 请记住,最高有效位(MSb)是符号位。 如果这个位是1,那么这个数字是负数。 如果它是一个零,这个数字是正数。 这是关键的信息丢失了第一个左移。 例如

 -32768<<4 

是一样的事情

 0x8000<<4 

(为了简单起见,假设一个16位的机器)

结果当然是0,这实际上没有任何意义,因此是UB。

在OP的访问问题的具体情况下,我们只关心一个具体的价值… 而不是一般情况。 -1(在32位机器上的0xffffffff)向左移动4次将产生0xfffffff0,正如OP最初所想的那样。

这是未定义的行为。

 $ cat undef.c #include <stdio.h> int main(void){ printf ("%x" ,-1<<4); } $ clang -fsanitize=undefined undef.c $ ./a.out undef.c:3:24: runtime error: left shift of negative value -1 fffffff0 

我在3个不同的编译器和操作系统上运行这个代码。 所有人都给了我这个问题中提到的同样的答案。 除非有人提出这个编译器的确是一个未定义的行为,否则我会说答案是正确的。 如果这种情况在99.99%的情况下是稳定的,那么标准变得更多的机会比编译器停止支持它更多。

我只是在一个文本文件中编写代码,编译它, 是的 ,答案是正确的。