面试问题


Just do it
2025-05-11 10:33:11 (1天前)
  1. 我被问到以下代码的输出


访问
</跨度>
昨天

include&lt; stdio.h&gt;

int main(void){
printf(“%x”, - 1&lt;&lt; 4);
}

我有2分钟时间告诉答案。我回复了fffffff0。结果

访问
</跨度>
尚未宣布。我想知道我的答案是否正确?

9 条回复
  1. 0# 哎?小查查 | 2019-08-31 10-32



    在我的机器上:




    1. chris@zack:~$ cat > test.c

    2. include

      int main(void){
      printf (“%x ,-1<<4);
      }

    3. chris@zack:~$ gcc -o test test.c && ./test
      fffffff0

    4. </code>


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


  2. 1# 冷月如霜·胡狼 | 2019-08-31 10-32



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


  3. 2# 一瓶泡沫 | 2019-08-31 10-32



    这是未定义的行为。




    1. $ cat undef.c

    2. include

      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. </code>

  4. 3# 至此 | 2019-08-31 10-32



    我只是在一个文本文件中编写代码,编译它,然后


    </强>
    ,答案是对的。


  5. 4# trpnest | 2019-08-31 10-32



    从技术上讲,左移一个负整数会调用Undefined Behavior。这意味着

    -1<<4

    是UB。我不知道为什么他们问你这个问题。可能他们想测试您对C和C ++标准的深度了解。



    C99 [

    6.5.7/4

    ]说




    E1&lt;&lt;&lt;&lt; E2是E1左移E2位位置;空位是铿乴以零为首。如果E1具有无符号类型,则结果的值为E1脳2

    E2

    ,减少模数
    比结果类型中可表示的最大值多一个。如果E1有签名
    类型和非负值,E1脳2

    E2

    在结果类型中是可表示的,那就是
    结果价值;

    否则,行为是不正确的
    </强>




    C ++ 03使其成为未定义的行为

    省略相关文字



  6. 5# 那年 | 2019-08-31 10-32



    左移一个负数是未定义的

    一般

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




    1. -32768<<4

    2. </code>


    是一样的




    1. 0x8000<<4

    2. </code>


    (假设16位机器简单)



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



    在OP的访谈问题的具体情况中,我们只关注一个具体的价值……



    一般情况。 -1(在32位机器上的0xffffffff)向左移动4次将产生0xfffffff0,正如OP最初想的那样。


  7. 6# 岁爵 | 2019-08-31 10-32




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

    2. </code>


    将1的出现替换为1,因为您要计算负数的二进制数




    如何计算负数的二进制数




    1. Binary of -1 : 1111 1111 1111 1111 1111 1111 1111 11111

    2. Left shift 4 : 1111 1111 1111 1111 1111 1111 1111 0000

    3. </code>


    十六进制结果左移4的表示
    将会




    1. 1111 : F

    2. 0000 : 0

    3. </code>


    所以计算的输出将是:




    1. FFFFFFF0

    2. </code>


    你的答案是正确的。


  8. 7# 那月静好 | 2019-08-31 10-32



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



    真正的答案是它是实现定义的。由于超载,我并不是100%有信心说它是未定义的行为,但我认为可能是。至少虽然结果取决于负数如何表示等等……你声称这两种语言都没有定义输出的内容。


登录 后才能参与评论