谜题 之 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 ...
随机推荐
- 面试Python工程师,这几道编码题有必要背背,Python面试题No8
第1题:列表[1,2,3,4,5],请使用map()函数输出[1,4,9,16,25],并使用列表推导式提取出大于10的数,最终输出[16,25]. map是python高阶用法,字面意义是映射,它的 ...
- linux 下常见命令
===============安装和登陆命令============================================================= Mount: 挂载命令.把存储介 ...
- mysql复制延迟排查
今天收到报警,提示从库延时,首先当然是上去查看情况,首先查看机器负载,如下: 可以看到使用cpu已经100%,io没有等待.那么查看mysql是什么情况,执行show processlist没有发现任 ...
- Linux快捷键列表
Linux快捷键列表 快捷键 功能描述 快捷键 功能描述 control+p 查询命令历史纪录的上一条命令 方向上键 查询命令历史纪录的上一条命令 control+n 查询命令历史纪录的下一条命令 方 ...
- Python第三方库之openpyxl(10)
Python第三方库之openpyxl(10) 雷达图 在工作表上的列或行中排列的数据可以在雷达图中绘制.雷达图比较多个数据系列的总值.它实际上是一个圆形x轴上的面积图的投影.有两种类型的雷达图:st ...
- FineMessBox的js依赖导致错误Uncaught ReferenceError: addEvent is not defined
/** * COMMON DHTML FUNCTIONS * These are handy functions I use all the time. * * By Seth Banks ( ...
- CSU-1336: Interesting Calculator,最短路思想!
1336: Interesting Calculator 这道题被LZQ抢了一血,于是去读题发现题意不难,纯广搜结果写的一塌糊涂. 题意:给你两个数x,y.由x每次可以经过一系列操作变换,每个变换都有 ...
- POJ 2914 Minimum Cut 全局最小割
裸的全局最小割了吧 有重边,用邻接矩阵的时候要小心 #include<iostream> #include<cstdio> #include<bitset> #in ...
- 【倒跑并查集维护连通块】NCPC 2016 A. Artwork
http://codeforces.com/gym/101550/attachments [AC] #include<bits/stdc++.h> using namespace std; ...
- Linux(11):期中架构(3)--- SSH远程管理服务 & ansible 批量管理服务
SSH远程管理服务 1. 远程管理服务知识介绍 # 1.1 SSH远程登录服务介绍说明 SSH是Secure Shell Protocol的简写,由 IETF 网络工作小组(Network Worki ...