> 文档中心 > 这十道题让我感觉我的C语言白学了

这十道题让我感觉我的C语言白学了

文章目录

  • 目录
  • 1. 第一题
  • 2. 第二题
  • 3. 第三题
  • 4. 第四题
  • 5. 第五题
  • 6. 第六题
  • 7. 第七题
  • 8. 第八题
  • 9. 第九题
  • 10. 第十题

目录

        下面这些十道题目都是C语言的经典易错题,也是面试过程中非常喜欢考的,假如一个题目是一关的话,快来闯关看看,你能通过第几关呢?

1. 第一题

【题目】
当输入为 1 2 时,下面程序的输出结果为:

#include int main(){    int a, b;    int ret1, ret2, ret3;    ret1 = scanf("%d%d", &a, &b);    ret2 = printf("a = %d, b = %d\n", a, b);    ret3 = printf("%s\n", "abc");    printf("ret1 = %d, ret2 = %d, ret3 = %d\n", ret1, ret2, ret3);    return 0;}

【解析】
其实这题考察点很简单,就是考察printf() 和 scanf() 这两个函数的返回值。这两个函数我们肯定会经常用到,但是他们俩的返回值确常常被大家忽略。scanf()函数成功返回读入的数据项数。printf()函数的返回值是打印到终端上的字符数。知道这个知识点后,由此我们就很容易知道了 ret1 的值是 2 。 那么ret2 的值是多少呢,要知道空格和换行符也是一个字符的哦,所以, ret2 的值就应该是 13 。那么 ret3 的值应该是多少呢,可能稍微思考一下的人就会认为是 5, 因为字符串是以 ‘\0’ 结尾的,再加上 ‘\n’, 所以认为是 5,但其实 printf() 函数的返回值是不算 ‘\0’ 的,这点是个例外,所以 ret3 的返回值就应该是 4 。
【答案】
ret1 = 2, ret2 = 13, ret3 = 4

2. 第二题

【题目】
在32位操作系统下,下面程序的输出结果为:

#include int main(){    int a = 5, b = 5;    b = sizeof(++a);    printf("a = %d, b = %d\n", a, b);    return 0;}

【解析】
其实这题考察点其实就是 sizeof 这个关键字了。很多人看到这个题目肯定会脱口而出,a 的值是 6, b 的值是 5 。但结果真的是这样的吗,要知道 sizeof 是在编译的时候执行的,而表达式是在运行的时候执行的,所以 sizeof 中的表达式并不会被执行,因此 a 就不会自增 1, 所以 a 的值还 5, 而在32位操作系统下,int 占 4 字节,所以 b 的值为 4 。
【答案】
a = 5, b = 4

3. 第三题

【题目】
下面程序的输出结果为:

#include int main(){    char a = 'A';    short b = 2;    int c = 3;    int ret1, ret2, ret3; ret1 = sizeof(a + c);    ret2 = sizeof(b + c);    ret3 = sizeof(a + b);    printf("ret1 = %d, ret2 = %d, ret3 = %d\n", ret1, ret2, ret3);    return 0;}

【解析】
其实这题考察点其实就是强制类型转换。在不同类型再做运算时,低类型回向高类型转换,并且 int 以下类型在做运算时,都会转换成 int 。因此 char 和 int 做运算时,表达式的结果会转换成 int, short 和 int 做运算也会转换成 int, char 和 short 做运算还是会转成 int 类型。
【答案】
ret1 = 4, ret2 = 4, ret3 = 4

4. 第四题

【题目】
下面这段代码能否正常输出?

#include int func();int main(){    printf("a =%d, a*a = %d\n", a, func());    return 0;}int a = 10;int func(){    return a * a;}

【解析】
这个题主要是考察全局变量的作用域。全局变量的作用域是从定义的位置开始到所在源文件的结束,在这区域内的才可以被访问。因为变量 a 定义在 main() 之后,func() 之前,所以 main() 函数是不能够访问 a 的,而 func() 函数可以对其进行访问。如果想在 main() 里面也访问 a, 可以将 a 定义在 main() 之前,或者在 mian() 前面对变量 a 进行 extern ,这两种方法都行。
【答案】
不能

5. 第五题

【题目】
下面程序的输出结果为:

#include int func(int a, int b){    printf("a = %d, b = %d\n", a, b);    return a + b;}int main(){ int x = 10;    int ret = 0;    ret = func(x, x++);    printf("ret = %d\n", ret);    return 0;}

【解析】
这个题主要是考察形参的传递方式,参数的传递是栈的方式进行的。参数的传递是从右往左进行的,相当于是先把 x++ 放入栈中, 也就是相当于将数值10放入了栈中,放入之后 x 会执行 ++ 操作,再把 x 放入栈中,此时 x 的值已经被 ++ 了,相当于放入的值是 11 。在取出栈中元素是,将取出的 11 赋值给了 a,再将 10 赋值给了 b, 所以 b = 10, a = 11,a + b = 21。
【答案】
a = 11, b = 10
ret = 21

6. 第六题

【题目】
下面程序的输出结果为:

#include int main(){    int a = 10;    switch (a)     { default:     break; case 10:     a++;     break;    }    printf("a = %d\n", a);    return 0;}

【解析】
这个题主要是考察在 switch…case 语句中 case 和 default 的关系。一般情况下我们都习惯把 default 写在最后面,可能会潜移默化的认为只要当编译器运行到 default 的时候就会执行,但其实不然,在switch…case语句中,default和case的位置没有关系,编译器都会先找case,等case不满足条件之后才会找default。这要要牢记。所以该程序中肯定会跳转执行 case 那里的代码,而不是执行 default 那里的代码,因此 a = 11。
【答案】
a = 11

7. 第七题

【题目】
下面程序的输出结果为:

#include func(double a, double b){    return a+b;}int main(){    double x = 0;    x = func(1.1, 2.2);    printf("x = %lf\n", x);    return 0;}

【解析】
这个题主要是考察函数的默认返回值。很多小伙伴可能认为这个题目输出的结果为 3.3 ,但其实不然,函数如果不写返回值的话,那么返回值默认就是 int 类型。因此 x 就是 3,所以输出就是 3 。
【答案】
x = 3.000000

8. 第八题

【题目】
for( ; ; )和while(1)有什么区别?
【解析】
咋一看,感觉这两种写法没啥区别,都是死循环。但细品之后,其实不然,while 循环里面 1 其实就是个表达式,相当于程序每次执行完一次循环后都会判断这个1是否满足条件,既然有判断那么就会存在寄存器的占用,而 for( ; ; )循环并不会。而从汇编的角度来看,for( ; ; )只用1条汇编指令,而 while(1)因为会占用寄存器,需要四条汇编语句才能执行完,由此可见,其实for( ; ; )的效率是要高于 while(1) 的。但有的编译器会对其进行优化,优化后两者并无太大差别。

9. 第九题

【题目】
任意给定一个数,怎么求每一位对应的数?
例如给定数 123456,怎么求万位对应的数,怎么求千位对应的数?
【解析】
任意一个数想取对应位的数时:
万能公式:这个数除以对应位数,再对10取余。
如123456,想取万位数时,123456/10000%10,想取千位数时,123456/1000%10即可

10. 第十题

【题目】
请自己实现一个sizeof
【提示】
其实这个题要从两方面看,sizeof既可以通过变量来求出所占用的字节大小,还可以通过类型来求出所占用的字节大小哦!大家先思考下该怎么解吧,下面有具体答案和解析哦!
【答案】
传变量 : #define SIZE(var) ((char *)(&var + 1) - (char *)&var)
传类型 : #define SIZE(type) ((char *)((type *)0 + 1) - (char *)0)
【解析】
对于传变量,假如传了一个 int 类型变量,那么取它的地址加一之后,变量类型就是 int * , int * 加一就是步进 4 字节,再将其转换成 char * 类型和原来的地址相减,就是中间隔的字节数了,所以这样就能够算出 int 所占用的字节数了。
对于传类型,假如还是传入 int 类型,我们将int型指针指向地址0,再加一,那也就是在地址4上面,我们再转换成char * 类型和 0地址相减就能算出所占用的字节数了。
其实这两种方法都是一样的道理,都是通过指针的步进来算出其所占用的字节数的。


上面十个题目有没有都做对的大佬呢?快来评论区来讨论下吧!

这十道题让我感觉我的C语言白学了 创作挑战赛 这十道题让我感觉我的C语言白学了 新人创作奖励来咯,坚持创作打卡瓜分现金大奖