青春如梦,岁月如花,流水似年,稍纵即逝。

嗨,这里是狐狸~~

今天是2022年的1月12日,距离过年还有18天,时间过得飞快,过了腊八就是年,学生们大都已经放假了吧,最近听了一句话,都说现在年越来越没有年味了,其实不然,只是快乐的人不再是你们了。

今天给大家来点不一样的,C语言的谜题库,一些迷惑性大的错题给大家做一个总结,应该会有大家常常放错的地方,希望看完之后,大家至少对于这些问题不会再犯错。

c语言思考题有哪些(15个C语言谜题)(1)

15个C语言的迷题1、下面的程序并不见得会输出 HelloWorld,你知道为什么吗?

#include #include int main() { while(1) { fprintf(stdout,"HelloWorld"); fprintf(stderr,"HelloWorld"); sleep(1); } return 0; }

参考答案:stdout和stderr是不是同设备描述符。stdout是块设备,stderr则不是。对于块设备,只有当下面几种情况下才会被输入,

1)遇到回车

2)缓冲区满

3)flush被调用。而stderr则不会。

2、下面的程序看起来是正常的,使用了一个逗号表达式来做初始化。可惜这段程序是有问题的。你知道为什么呢?

#include int main() { int a = 1,2; printf("a : %d\n",a); return 0; }

参考答案:这个程序会得到编译出错(语法出错),逗号表达式是没错,可是在初始化和变量声明时,逗号并不是逗号表达式的意义。这点要区分,要修改上面这个程序,你需要加上括号: int a = (1,2);

3、下面的程序会有什么样的输出呢?

#include int main() { int i=43; printf("%d\n",printf("%d",printf("%d",i))); return 0; }

参考答案:程序会输出4321,你知道为什么吗?要知道为什么,你需要知道printf的返回值是什么。printf返回值是输出的字符个数。

3、根据考试成绩的等级打印出百分制数段。

switch(grade) { case 'A':printf("85~100\n"); case 'B':printf("70~84\n"); case 'C':printf("60~69\n"); case 'D':printf("<60\n"); default:printf("error\n");

参考答案:由于漏写了break语句,case只起标号的作用,而不起判断作用。因此,当grade值为A时,printf函数在执行完第一个语句后接着执行第二、三、四、五个printf函数语句。正确写法应在每个分支后再加上“break;”。例如

case 'A':printf("85~100\n");break;

4、忽视了while和do-while语句在细节上的区别

main()   {int a=0,I;   scanf("%d",&I);   while(I<=10)   {a=a I;   I ;   }   printf("%d",a);   }   (2)main()   {int a=0,I;   scanf("%d",&I);   do   {a=a I;   I ;   }while(I<=10);   printf("%d",a);   }

参考答案:可以看到,当输入I的值小于或等于10时,二者得到的结果相同。而当I>10时,二者结果就不同了。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于10的数while循环一次也不执行循环体,而do-while语句则要执行一次循环体。

5、定义数组时误用变量

 int n;   scanf("%d",&n);   int a[n];

参考答案:数组名后用方括号括起来的是常量表达式,可以包括常量和符号常量。即C不允许对数组的大小作动态定义。

6、请说出下面的程序输出是多少?并解释为什么?(注意,该程序并不会输出 "b is 20")

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

参考答案:该程序在编译时,可能会出现一条warning: unreachable code at beginning of switch statement。我们以为进入switch后,变量b会被初始化,其实并不然,因为switch-case语句会把变量b的初始化直接就跳过了。所以,程序会输出一个随机的内存值。

7、请问下面的程序会有什么潜在的危险?

#include int main() { char str[80]; printf("Enter the string:"); scanf("%s",str); printf("You entered:%s\n",str); return 0; }

参考答案:本题很简单了。这个程序的潜在问题是,如果用户输入了超过80个长度的字符,那么就会有数组越界的问题了,你的程序很有可以及会crash了。

8、请问下面的程序输出什么?

#include int main() { int i; i = 10; printf("i : %d\n",i); printf("sizeof(i ) is: %d\n",sizeof(i )); printf("i : %d\n",i); return 0; }

参考答案:如果你觉得输出分别是,10,4,11

那么你就错了,错在了第三个,第一个是10没有什么问题,第二个是4,也没有什么问题,因为是32位机上一个int有4个字节。但是第三个为什么输出的不是11呢?居然还是10?原因是,sizeof不是一个函数,是一个操作符,其求i 的类型的size,这是一件可以在程序运行前(编译时)完全的事情,所以,sizeof(i )直接就被4给取代了,在运行时也就不会有了i 这个表达式。

9、在定义数组时,将定义的“元素个数”误认为是可使的最大下标值

main()   {static int a[10]={1,2,3,4,5,6,7,8,9,10};   printf("%d",a[10]);   }

参考答案:C语言规定:定义时用a[10],表示a数组有10个元素。其下标值由0开始,所以数组元素a[10]是不存在的。

10、请问下面的程序输出是什么?(绝对不是10)

#include #define PrintInt(expr) printf("%s : %dn",#expr,(expr)) int main() { int y = 100; int *p; p = malloc(sizeof(int)); *p = 10; y = y/*p; /*dividing y by *p */; PrintInt(y); return 0; }

参考答案:本题输出的是100。为什么呢?问题就出在 y = y/*p;上了,我们本来想的是 y / (*p) ,然而,我们没有加入空格和括号,结果y/*p中的 /*被解释成了注释的开始。于是,这也是整个恶梦的开始。

11、下面的输出是什么?

#include int main() { int i = 6; if( (( i < 7) && ( i /6)) || ( i <= 9)); printf("%d\n",i); return 0; }

参考答案:本题并不简单的是考前缀 或反缀 ,本题主要考的是&&和||的短路求值的问题。所为短路求值:对于(条件1 && 条件2),如果“条件1”是false,那“条件2”的表达式会被忽略了。对于(条件1 || 条件2),如果“条件1”为true,而“条件2”的表达式则被忽略了。所以,我相信你会知道本题的答案是什么了。

12、下面的C程序是合法的吗?如果是,那么输出是什么?

#include int main() { int a=3, b = 5; printf(&a["Ya!Hello! how is this? %s\n"], &b["junk/super"]); printf(&a["WHAT%c%c%c %c%c %c !\n"], 1["this"],2["beauty"],0["tool"],0["is"],3["sensitive"],4["CCCCCC"]); return 0; }

参考答案:本例是合法的,输出如下:

Hello! how is this? super That is C ! 本例主要展示了一种另类的用法。下面的两种用法是相同的:

"hello"[2] 2["hello"]

如果你知道:a[i] 其实就是 *(a i)也就是 *(i a),所以如果写成 i[a] 应该也不难理解了。

13、请问下面的程序输出什么?(假设:输入 Hello, World)

#include int main() { char dummy[80]; printf("Enter a string:\n"); scanf("%[^r]",dummy); printf("%s\n",dummy); return 0; }

参考答案:本例的输出是“Hello, Wo”,scanf中的"%[^r]"是从中作梗的东西。意思是遇到字符r就结束了。

14、在不应加地址运算符&的位置加了地址运算符。

scanf("%s",&str);

参考答案:C语言编译系统对数组名的处理是:数组名代表该数组的起始地址,且scanf函数中的输入项是字符数组名,不必要再加地址符&。应改为:

scanf("%s",str);

15、 同时定义了形参和函数中的局部变量

int max(x,y)   int x,y,z;   {z=x>y?x:y;   return(z);   }

参考答案:形参应该在函数体外定义,而局部变量应该在函数体内定义。应改为:

int max(x,y) int x,y; {int z; z=x>y?x:y; return(z); }

总结

本篇文章展示了14个C语言的迷题以及答案,代码应该是足够清楚的,而且我也相信有相当的一些例子可能是我们日常工作可能会见得到的。通过这些迷题,希望你们能更了解C语言。如果你不看答案,不知道是否有把握回答各个谜题?大家都可以去尝试哈!

后续我还会发布更多的项目源或者学习资料,希望大家可以持续关注,有什么问题可以回帖留言。领取C/C 学习资料以及其他项目的源码的可以加群【1083227756】了解。想要对程序员的未来发展有兴趣的可以关注【狐狸的编码时光】,希望和大家一起学习进步!

c语言思考题有哪些(15个C语言谜题)(2)

,