我昨天在采访中被问到以下代码的输出
#include <stdio.h>
int main(void){
printf ("%x" ,-1<<4);
}
我有2分钟时间告诉答案。我回复了fffffff0
。采访结果尚未宣布。我想知道我的答案是否正确?
答案 0 :(得分:58)
技术上左移一个负整数会调用Undefined Behavior。这意味着-1<<4
是UB。我不知道为什么他们问你这个问题。可能他们想测试你对C和C ++标准的深度了解。
C99 [6.5.7/4
]说
E1的结果&lt;&lt; E2是E1左移E2位位置;腾出的位用零填充。如果E1具有无符号类型,则结果的值为E1×2 E2 ,减少模数 比结果类型中可表示的最大值多一个。如果E1有签名 类型和非负值,E1×2 E2 在结果类型中可表示,那么 结果价值; 否则,行为未确定。
C ++ 03使omitting the relevant text的行为未定义。
答案 1 :(得分:11)
没有。你不对。这是坏消息。好消息是,面试官可能不知道这一点,并且会认为你是因为这是他们编译运行时得到的结果。
真正的答案是它是实现定义的。由于超载,我并不是100%有信心说它是未定义的行为,但我认为可能是。至少虽然结果取决于负数如何表示等等......你声称这两种语言都没有定义输出的内容。
答案 2 :(得分:9)
在我的机器上:
chris@zack:~$ cat > test.c
#include <stdio.h>
int main(void){
printf ("%x" ,-1<<4);
}
chris@zack:~$ gcc -o test test.c && ./test
fffffff0
但是,结果将取决于您的体系结构和编译器。所以正确的答案是“它可以输出任何东西。”
答案 3 :(得分:8)
Binary of 1 : 0000 0000 0000 0000 0000 0000 0000 00001
将1的出现替换为1,因为您要计算负数的二进制
How to calculate binary of negative numbers
Binary of -1 : 1111 1111 1111 1111 1111 1111 1111 11111
Left shift 4 : 1111 1111 1111 1111 1111 1111 1111 0000
十六进制结果左移4的表示 将是
1111 : F
0000 : 0
如此计算的输出将是:
FFFFFFF0
你的答案是对的。
答案 4 :(得分:3)
左移一个负数是未定义的,但是我们必须理解为什么这个未定义的行为(UB)?请记住,最高有效位(MSb)是符号位。如果该位为1,则该数字为负。如果它为零,则数字为正。这是第一次左移时丢失的关键信息。例如
-32768<<4
与
相同0x8000<<4
(假设一台16位机器为了简单起见)
结果当然是0,这实际上没有任何意义,因此是UB。
在OP的访谈问题的具体情况中,我们只关注一个特定的值... not 一般情况。 -1(32位机器上的0xffffffff)向左移动4次将产生0xfffffff0,就像OP最初想的那样。
答案 5 :(得分:1)
这是未定义的行为。
$ 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
答案 6 :(得分:-1)
我在3个不同的编译器和操作系统上运行此代码。所有人都给了我同样的答案,如问题所述。除非有人提出编译器,这是真正未定义的行为,我会说答案是正确的。如果在99.99%的情况下这是稳定的,那么标准变更的机会比编译器停止支持它的机会多。
答案 7 :(得分:-4)
我只是在一个文本文件中编写代码,编译它,然后是,答案是正确的。