C语言经典面试题详解(第1节)

程序员们求职时,常常会被要求回答一些“奇葩”而又不实用的问题,但这些题目确实能够从某种程度上反映出一个人的技术水平,作为求职者的我们,既然无力改变这种招聘流程,就只能努力提升自己——从这些“奇葩”的面试题目中找出自己的不足。

先来看看这个问题

以下C语言代码输出什么?这个题目出自台湾某著名杀毒软件公司的笔试题。

int k = 8;
void main()
{
    int k=k;
    printf("%d\n", k);
}

A. 输出 k=随机数
B. 输出 k=8
C. 编译报错
D. 输出 k=0

这个题目看起来的确很怪异,而且我相信在实际开发中,没有程序员会写这样的代码。但是现在先就题论题,答案是哪一个呢,以及为什么呢?得到答案最简单粗暴的方法就是做实验,所以新建 t.c 文件输入以上代码,编译执行结果如下:

# gcc t.c
# ./a.out
0

这里显示的是 0,那答案就选 D 咯?还不能这么早下结论,来考虑一下为什么程序会输出 0。考虑这种类型的问题,显然应该从编译器的角度出发。程序员们写出的 C语言代码需要被编译为可执行文件才能被投入运行,编译的总体流程如下:

C语言源代码是以字节流的形式存储在磁盘中的,词法分析负责从字节流从整理彼此独立的词语,方便进行语法分析。语法分析器遇到 int k 时,一般会立即将其标记为 int 型的变量,然后再继续分析之后的内容。所以对于语法分析器来说, int k = k 这样奇怪的语句其实相当于下面这两句:

int k;
k = k;

这就明白了,这两句其实就是定义了一个 int 型变量,并且将它赋值给自己。现在我们改写一下上面的题目:

int k = 8;
void main()
{
    int k;
    k = k;
    printf("%d\n", k);
}

答案已经很明确了,printf 里的 k 显然是属于 main() 里的定义的局部变量 k,而这里的 k 并没有赋初值,所以最终输出的值是随机的,未定义的,应该选 A。

再看一个问题

下面这段C语言程序输出什么?这个问题出自国内某著名互联网公司的笔试题目。

#include <stdio.h>

int main()
{
     int a, x;
     for(a=0,x=0; a<=1 && !x++; )
         a++;
     printf("a=%d, x=%d\n", a, x);

     for(a=0,x=0; a<=1 && !x++; a++)
         a++;
     printf("a=%d, x=%d\n", a, x);

     return 0;
}


先来看第一个 printf,在 for 中 a 和 x 都被赋初值为 0,接着按照如下流程执行:

  • 此时 a=0,x=0,判断 a<=1 && !x++,为真,执行了 a++;
  • 此时 a=1,x=1,判断 a<=1 && !x++,为假,跳出 for;
  • 此时 a=1,x=2。

再来分析一下第二个 printf,在 for 中 a 和 x 都被赋初值为 0,接着按照如下流程执行:

  • 此时 a=0,x=0,判断 a<=1 && !x++,为真,执行了 for 外的 a++;
  • 执行 for 里的 a++, 此时 a=2,x=1,判断 a<=1 && !x++,为假,跳出 for;
  • 此时 a=2,x=1。

到这里,相信大家应该已经知道上面的 C 语言程序会输出什么了,这里再写一下吧:

# ./a.out 
a=1, x=2
a=2, x=1

分析该问题的关键在于C语言中 a&&b 表达式的处理,需要注意的是这一点:如果 a 为假,就已经能够判断 a&&b 整个表达式为假了,因此 b 就不会被执行了。只有 a 为真,b 才有机会被执行。

类似的表达式还有 a||b,读者能够分析出什么情况下,b 不会被执行吗?
阅读更多:   C语言
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif