谜题 之 C语言
本篇文章展示了14个C语言的迷题以及答案。代码应该是足够清楚的,并且我也相信有相当的一些样例可能是我们日常工作可能会见得到的。通过这些迷题,希望你能更了解C语言。假设你不看答案。不知道是否有把握回答各个谜题?让我们来试试。
1、以下的程序并不见得会输出 hello-std-out,你知道为什么吗?
01.
#include
<stdio.h>
02.
#include
<unistd.h>
03.
int
main()
04.
{
05.
while
(1)
06.
{
07.
fprintf
(stdout,
"hello-std-out"
);
08.
fprintf
(stderr,
"hello-std-err"
);
09.
sleep(1);
10.
}
11.
return
0;
12.
}
參考答案:stdout和stderr是不是同设备描写叙述符。
stdout是块设备。stderr则不是。对于块设备,仅仅有当以下几种情况下才会被输入,1)遇到回车,2)缓冲区满。3)flush被调用。而stderr则不会。
2、以下的程序看起来是正常的,使用了一个逗号表达式来做初始化。
可惜这段程序是有问题的。
你知道为什么呢?
2.
3.
int
main()
4.
{
5.
int
a
= 1,2;
6.
printf
(
"a
: %d "
,a);
7.
return
0;
8.
}
參考答案:这个程序会得到编译出错(语法出错),逗号表达式是没错,但是在初始化和变量声明时,逗号并非逗号表达式的意义。这点要区分,要改动上面这个程序,你须要加上括号: int a = (1,2);
3、以下的程序会有什么样的输出呢?
2.
int
main()
3.
{
4.
int
i=43;
5.
printf
(
"%d
"
,
printf
(
"%d"
,
printf
(
"%d"
,i)));
6.
return
0;
7.
}
參考答案:程序会输出4321,你知道为什么吗?要知道为什么。你须要知道printf的返回值是什么。
printf返回值是输出的字符个数。
4、以下的程序会输出什么?
02.
int
main()
03.
{
04.
float
a
= 12.5;
05.
printf
(
"%d
"
, a);
06.
printf
(
"%d
"
, (
int
)a);
07.
printf
(
"%d
"
, *(
int
*)&a);
08.
return
0;
09.
}
參考答案:
该项程序输出例如以下所看到的。
0
12
1095237632
原因是:浮点数是4个字节,12.5f 转成二进制是:01000001010010000000000000000000。十六进制是:0×41480000。十进制是:1095237632。所以。第二和第三个输出相信大家也知道是为什么了。而对于第一个。为什么会输出0,我们须要了解一下float和double的内存布局,例如以下:
- float: 1位符号位(s)、8位指数(e)。23位尾数(m,共32位)
- double: 1位符号位(s)、11位指数(e),52位尾数(m,共64位)
然后,我们还须要了解一下printf因为类型不匹配,所以。会把float直接转成double,注意,12.5的float和double的内存二进制全然不一样。别忘了在x86芯片下使用是的反字节序,高位字节和低位字位要反过来。所以:
- float版:0×41480000 (在内存中是:00 00 48 41)
- double版:0×4029000000000000 (在内存中是:00 00 00 00 00 00 29 40)
而我们的%d要求是一个4字节的int,对于double的内存布局,我们能够看到前四个字节是00,所以输出自然是0了。
这个演示样例向我们说明printf并非类型安全的,这就是为什么C++要引如cout的原因了。
5、以下,我们再来看一个交叉编译的事情。以下的两个文件能够编译通过吗?假设能够通过,结果是什么?
file1.c
file2.c
2.
int
main()
3.
{
4.
arr[1]
= 100;
5.
printf
(
"%d
"
, arr[1]);
6.
return
0;
7.
}
參考答案:该程序能够编译通过,但执行时会出错。
为什么呢?原因是,在还有一个文件里用 extern int *arr来外部声明一个数组并不能得到实际的期望值,由于他们的类型并不匹配。
所以导致指针实际并没有指向那个数组。注意:一个指向数组的指针,并不等于一个数组。改动:extern int arr[]。(參考:ISO C语言 6.5.4.2 节)
6、请说出以下的程序输出是多少?并解释为什么?(注意。该程序并不会输出 “b is 20″)
02.
int
main()
03.
{
04.
int
a=1;
05.
switch
(a)
06.
{
07.
int
b=20;
08.
case
1:
09.
printf
(
"b
is %d "
,b);
10.
break
;
11.
default
:
12.
printf
(
"b
is %d "
,b);
13.
break
;
14.
}
15.
return
0;
16.
}
參考答案:该程序在编译时。可能会出现一条warning: unreachable code at beginning of switch statement。我们以为进入switch后,变量b会被初始化。事实上并不然,由于switch-case语句会把变量b的初始化直接就跳过了。所以,程序会输出一个随机的内存值。
7、请问以下的程序会有什么潜在的危急?
02.
int
main()
03.
{
04.
char
str[80];
05.
printf
(
"Enter
the string:"
);
06.
scanf
(
"%s"
,str);
07.
printf
(
"You
entered:%s "
,str);
08.
return
0;
09.
}
參考答案:本题非常easy了。这个程序的潜在问题是。假设用户输入了超过80个长度的字符。那么就会有数组越界的问题了,你的程序非常有能够及会crash了。
8、请问以下的程序输出什么?
02.
int
main()
03.
{
04.
int
i;
05.
i
= 10;
06.
printf
(
"i
: %d "
,i);
07.
printf
(
"sizeof(i++)
is: %d "
,
sizeof
(i++));
08.
printf
(
"i
: %d "
,i);
09.
return
0;
10.
}
參考答案:假设你认为输出各自是,10。4,11,那么你就错了,错在了第三个,第一个是10没有什么问题。第二个是4,也没有什么问题,由于是32位机上一个int有4个字节。可是第三个为什么输出的不是11呢?竟然还是10?原因是,sizeof不是一个函数。是一个操作符,其求i++的类型的size,这是一件能够在程序执行前(编译时)全然的事情。所以,sizeof(i++)直接就被4给代替了,在执行时也就不会有了i++这个表达式。
9、请问以下的程序的输出值是什么?
02.
#include
<stdlib.h>
03.
04.
#define
SIZEOF(arr) (sizeof(arr)/sizeof(arr[0]))
05.
#define
PrintInt(expr) printf("%s:%d ",#expr,(expr))
06.
07.
int
main()
08.
{
09.
/*
The powers of 10 */
10.
int
pot[]
= {
11.
0001,
12.
0010,
13.
0100,
14.
1000
15.
};
16.
17.
int
i;
18.
for
(i=0;i<SIZEOF(pot);i++)
19.
PrintInt(pot[i]);
20.
21.
return
0;
22.
}
參考答案:好吧。假设你对于PrintInt这个宏有问题的话。你能够去看一看《语言的歧义》中的第四个演示样例。只是。本例的问题不在这里,本例的输出会是:1。8,64,1000,事实上非常easy了,以C/C++中。以0开头的数字都是八进制的。
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、以下的输出是什么?
02.
int
main()
03.
{
04.
int
i
= 6;
05.
if
(
((++i < 7) && ( i++/6)) || (++i <= 9))
06.
;
07.
08.
printf
(
"%d
"
,i);
09.
return
0;
10.
}
參考答案:本题并不简单的是考前缀++或反缀++。本题主要考的是&&和||的短路求值的问题。所为短路求值:对于(条件1 && 条件2),假设“条件1”是false,那“条件2”的表达式会被忽略了。对于(条件1 || 条件2),假设“条件1”为true,而“条件2”的表达式则被忽略了。所以,我相信你会知道本题的答案是什么了。
12、以下的C程序是合法的吗?假设是,那么输出是什么?
02.
int
main()
03.
{
04.
int
a=3,
b = 5;
05.
06.
printf
(&a[
"Ya!Hello!
how is this?
%s "
], &b[
"junk/super"
]);
07.
08.
printf
(&a[
"WHAT%c%c%c
%c%c %c ! "
], 1[
"this"
],
09.
2[
"beauty"
],0[
"tool"
],0[
"is"
],3[
"sensitive"
],4[
"CCCCCC"
]);
10.
11.
return
0;
12.
}
參考答案:
本例是合法的,输出例如以下:
Hello! how is this? super
That is C !
本例主要展示了一种另类的使用方法。以下的两种使用方法是同样的:
“hello”[2]
2["hello"]
假设你知道:a[i] 事实上就是 *(a+i)也就是 *(i+a),所以假设写成 i[a] 应该也不难理解了。
13、请问以下的程序输出什么?(如果:输入 Hello, World)
01.
#include
<stdio.h>
02.
int
main()
03.
{
04.
char
dummy[80];
05.
printf
(
"Enter
a string: "
);
06.
scanf
(
"%[^r]"
,dummy);
07.
printf
(
"%s
"
,dummy);
08.
return
0;
09.
}
參考答案:本例的输出是“Hello, Wo”,scanf中的”%[^r]“是从中作梗的东西。意思是遇到字符r就结束了。
14、以下的程序试图使用“位操作”来完毕“乘5”的操作,只是这个程序中有个BUG,你知道是什么吗?
01.
#include
<stdio.h>
02.
#define
PrintInt(expr) printf("%s : %d ",#expr,(expr))
03.
int
FiveTimes(
int
a)
04.
{
05.
int
t;
06.
t
= a<<2 + a;
07.
return
t;
08.
}
09.
10.
int
main()
11.
{
12.
int
a
= 1, b = 2,c = 3;
13.
PrintInt(FiveTimes(a));
14.
PrintInt(FiveTimes(b));
15.
PrintInt(FiveTimes(c));
16.
return
0;
17.
}
參考答案:本题的问题在于函数FiveTimes中的表达式“t = a<<2 + a;”,对于a<<2这个位操作。优先级要比加法要低。所以这个表达式就成了“t = a << (2+a)”,于是我们就得不到我们想要的值。该程序修正例如以下:
1.
int
FiveTimes(
int
a)
2.
{
3.
int
t;
4.
t
= (a<<2) + a;
5.
return
t;
6.
}
谜题 之 C语言的更多相关文章
- Java解惑五:类之谜
本文是依据JAVA解惑这本书,做的笔记.电子书见:http://download.csdn.net/detail/u010378705/7527721 谜题46 函数重载的问题. JAVA重载解析过程 ...
- 转载:C语言的谜题
转载:http://coolshell.cn/articles/945.html 这几天,本站推出了几篇关于C语言的很多文章如下所示: 语言的歧义 [酷壳链接] [CSDN链接] 谁说C语言很简单? ...
- C 语言整型谜题
如题,此篇文章是描述C语言中的整数谜题. 假定机器字长是32位的,用2的补码表示整数.对以下C表达式,请问它们在所有情况下都正确吗?如果不是,请给出反例. 初始化: 1 2 3 4 int x = f ...
- C语言的谜题
本篇文章<C语言的谜题>展示了14个C语言的迷题以及答案,代码应该是足够清楚的,而且我也相信有相当的一些例子可能是我们日常工作可能会见得到的.通过这些迷题,希望你能更了解C语言.如果你不看 ...
- 解了这14道C语言谜题后,所有人都失声了!我来带你深入了解C!
本文展示了14个C语言的迷题以及答案,代码应该是足够清楚的,而且有相当的一些例子可能是我们日常工作可能会见得到的.通过这些迷题,希望你能更了解C语言. 如果你不看答案,不知道是否有把握回答各个谜题?让 ...
- 15 Puzzle (4乘4谜题) IDA*(DFS策略与曼哈顿距离启发) 的C语言实现
大家好!这是我的第一篇博客,由于之前没有撰写博客的经验,并且也是初入计算机和人工智能领域,可能有些表述或者理解不当,还请大家多多指教. 一.撰写目的 由于这个学期在上算法与数据结构课程的时候,其中一个 ...
- 谜题(JAVA语言)
package 第三章习题; /* * 有一个5*5的网络,其中恰好有一个格子是空的,其他格子各有一个字母. * 一个有4种指令:A, B, L, R, 分别表示把空格上.下.左.右的相邻字母移到 ...
- [变]C#谜题(1-10)表达式篇
[变]C#谜题(1-10)表达式篇 最近偶然发现了<Java谜题>,很有意思,于是转到C#上研究一下. 本篇是关于表达式的一些内容. 谜题1:奇数性(负数的取模运算) 下面的方法意图确定它 ...
- 深入理解c语言_从编译器的角度考虑问题_纪念Dennis Ritchie先生
开源中国: Dennis Ritchie教授过世了,他发明了C语言,一个影响深远并彻底改变世界的计算机语言.一门经历40多年的到今天还长盛不训的语言,今天很多语言都受到C的影 响,C++,Java,C ...
随机推荐
- Hive 执行sql命令报错
Failed with exception java.io.IOException:java.lang.IllegalArgumentException: java.net.URISyntaxExce ...
- iOS 引入支付宝 缺少 #include <openssl/asn1.h>
出现情况如上图: 解决方法如下:在你的Xcode里的header search paths 里添加支付宝SDK(openssl的路径):格式如下 $(PROJECT_DIR)/文件夹名 ...
- ubuntu14.04 software-center can not open
sudo apt-get update sudo apt-get dist-upgrade sudo apt-get install --reinstall software-center
- 鼠标移动或者鼠标点击div消失不见排查
点击事件,导致某div或者容器样式隐藏,如果不能直接发现click事件绑定,那么首先排查哪些方法在控制div的样式, 然后看一看哪些方法在调用修改样式的方法. 然后再排查什么在调用修改样式的方法的方法 ...
- 【Luogu】P2522Problemb(莫比乌斯反演)
题目链接 同Zip—Queries,但是用到容斥原理 设f(n,m)是(x,y)的对数,其中1<=x<=n,1<=y<=m 则有f(n,m)-f(a-1,n)-f(b-1,m) ...
- hdfs api读写文写件个人练习
看下hdfs的读写原理,主要是打开FileSystem,获得InputStream or OutputStream: 那么主要用到的FileSystem类是一个实现了文件系统的抽象类,继承来自org. ...
- 【kmp+最小循环节】poj 2406 Power Strings
http://poj.org/problem?id=2406 [题意] 给定字符串s,s=a^n,a是s的子串,求n最大是多少 [思路] kmp中的next数组求最小循环节的应用 例如 ababab ...
- 【bzoj1854】[Scoi2010]游戏 - 并查集
lxhgww最近迷上了一款游戏,在游戏里,他拥有很多的装备,每种装备都有2个属性,这些属性的值用[1,10000]之间的数表示.当他使用某种装备时,他只能使用该装备的某一个属性.并且每种装备最多只能使 ...
- angular中多控制器的依赖注入写法
直接看图,每个控制器有自己的名称,第二个参数中有需要注入的依赖对象,最后是我们的自定义函数,这样我们可以以模块化的方式进行书写.
- R语言入门视频笔记--3--列表list
list <- (stud.id = 1234,stud.name="Tom",stud,marks=c(18,3,14,25,19)) #生成一个列表,里面有学生id,学生 ...