你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

10个C语言的迷题以及答案

[复制链接]
gaosmile 发布时间:2020-10-12 22:46
本文展示了10个C语言的迷题以及答案,而且有相当的一些例子可能是我们日常工作可能会见得到的。通过这些迷题,希望你能更了解C语言。

# a/ L3 {! {7 L3 ~% ^: ?' U
如果你不看答案,不知道是否有把握回答各个谜题?让我们来试试。
. G. p6 c, x9 T% g. r, t
1
会输出"hello-std-out"?
; S) T) B/ ]9 z1 `
#include<stdio.h>) P* G( d9 B* Q( H1 `
int main()+ x  ~* {8 N# T2 y6 `- y
{
* h/ T' g+ n8 |% C& X& t" |while (1)
' [" }+ c6 V' Y% B    {1 g: k# S  W0 W, N0 c5 }$ r
        fprintf(stdout, "hello-std-out");/ E* Z. I' n0 H
        fprintf(stderr, "hello-std-err");" `% p) [8 I( X1 g' x) v
        sleep(1);# E( |) h* B" Z  W
    }
" q" c3 ?6 g1 J$ n+ a    return 0;
6 \# x" s" H5 M# s) O+ C}
& k, [. f0 m: V* @
2 N9 @& {5 a+ Z/ S( E0 ?8 Y
参考答案:
stdout和stderr是不同设备描述符。stdout是块设备,stderr则不是。对于块设备,只有当下面几种情况下才会被输入:遇到回车;缓冲区满;flush被调用。而stderr则不会。
2
这段程序是有问题吗?
% x& h/ G+ C# t5 T# J; P( n4 _" M
#include<stdio.h>/ ?- E" U% M& m$ ^. U) d
int main()% a; h0 I5 E' {4 Q0 }
{
8 K1 I/ P) o; ^    int a = 1,2;0 K5 [8 a4 y  ^* [
    printf("a : %d\n",a);
, Y1 I  I+ t2 |& S3 z8 A    return 0;
9 h6 N7 c7 m* c6 [- r3 J. E1 C  d}7 L; c2 `8 e& r
参考答案:
这个程序会得到编译出错(语法出错)。逗号表达式是没错,可是在初始化和变量声明时,逗号并不是逗号表达式的意义。这点要区分,要修改上面这个程序,你需要加上括号:"int a = (1,2);"。
) H0 N$ Z9 \' [
3
下面的程序会有什么样的输出呢?
, {3 J, Z6 [3 F/ H  Y0 l
#include<stdio.h>
6 C8 u7 W( i& {# S: }5 m+ K- ^! Iint main()
( `. k# v# }- x( G. P5 s{
! C% p$ X% h3 }" m# ]6 H9 R+ u" O* p& s    int i=43;
8 W" ~6 I, O0 i2 R0 f/ a" \    printf("%d\n",printf("%d",printf("%d",i)));
" l0 J) E' R1 j& f    return 0;& m6 b# j4 ~  t8 J5 P( n' v4 ]1 R
}
) J' {% W' a% w5 ]$ b
参考答案
程序会输出4321,你知道为什么吗?要知道为什么,你需要知道printf的返回值是什么。printf返回值是输出的字符个数。

6 }$ q! ^. H& U, ^) k8 {7 x& I
4
下面的程序会输出什么?

2 r1 E# t7 L1 D4 m+ l2 r2 Y1 C  g
#include<stdio.h>
. N0 D0 O7 t$ E4 L9 O) _9 Lint main()0 o. Y0 n( V) R- h. B
{
5 Y5 E* Z/ K* v0 ~5 x& tfloat a = 12.5;% [/ l0 ]+ ^3 |. _+ ^
printf("%d\n", a);* r" e$ J* e) a( y& I
printf("%d\n", (int)a);6 J7 j  Q! l& e4 x( A8 g* |, f
printf("%d\n", *(int*)&a);
+ C0 i8 W' s' m; N4 `; u+ w4 Oreturn 0;: e& _  m0 v( y, p/ f6 c  y  U$ {
}
9 p2 `2 H" o0 F: n& `
参考答案
该项程序输出:"0 12 1095237632"。
原因是:浮点数是4个字节,12.5f转成二进制是:01000001010010000000000000000000,十六进制是:0x41480000,十进制是:1095237632。所以,第二和第三个输出相信大家也知道是为什么了。
而对于第一个,为什么会输出0,我们需要了解一下float和double的内存布局,如下:
  • float: 1位符号位(s)、8位指数(e),23位尾数(m,共32位)。
  • double: 1位符号位(s)、11位指数(e),52位尾数(m,共64位)。

    0 q8 x+ r5 W1 n" ]* c5 |! X' D& ?
然后,我们还需要了解一下printf由于类型不匹配,所以,会把float直接转成double,注意,12.5的float和double的内存二进制完全不一样。别忘了在x86芯片下使用是的反字节序,高位字节和低位字位要反过来。所以:
  • float版:0x41480000 (在内存中是:00 00 48 41)。
  • double版:0x4029000000000000 (在内存中是:00 00 00 00 00 00 29 40)。
    & U: i9 V; n0 S1 V, Y/ ~, x
而我们的%d要求是一个4字节的int,对于double的内存布局,我们可以看到前四个字节是00,所以输出自然是0了。这个示例向我们说明printf并不是类型安全的,这就是为什么C++要引如cout的原因了。

, F5 g% r* G: G+ U* J
5
下面的程序输出是多少?并解释为什么?

$ I( p) I- d8 @" X* k  e3 R. n
#include<stdio.h>( p" N" b& c8 c- z; @" m. k$ D9 z
int main()2 g4 A* @% s4 R
{
# a; C# O$ @. c: k" M6 @: qint a = 1;
  O( R# \7 @& }% Eswitch (a)% P( |) o5 }6 s5 w* R6 `8 t
{
- B. X3 h# D) i' xint b = 20;
1 ?8 q3 `+ f- F# w5 \6 e1 C6 z/ jcase 1:
- f$ G  p, I# A! ]9 Pprintf("b is %d\n", b);
8 [+ Y5 W8 R% k4 A" Qbreak;6 f7 R) Q6 P# X. V
default:9 \$ T4 h+ l. B5 r2 i
printf("b is %d\n", b);% A' U- I' g9 ~; X
break;2 D, r( g' N7 c( C6 K
}  m4 @3 Z7 I; I+ J
return 0;
! j# Y  d! C. g/ r3 `, w$ U$ d/ k}/ I6 P6 X9 A' y3 B5 M% z9 M
参考答案
该程序在编译时,报错:“b”的初始化操作由“case”标签跳过,“default”标签跳过“b”的初始化操作
5 k) {; [* P) C3 z6 o4 i% k$ W
6
下面的程序会有什么潜在的危险?
/ C, G3 ?* ^2 A8 C- O
#include<stdio.h>
# v, l, h$ m3 ]int main()
' [+ n1 }1 Y, g2 e# ^{1 g1 F4 e; m( k
char str[10];
) c$ @8 V' W7 ]- M' _# Zprintf("Enter the string:");
! O# G- ?2 G. X" G' Xscanf("%s", str);  o. e" N9 E- \  V7 A2 q# J( N* o
printf("You entered:%s\n", str);
* M, }) m. K* V9 j0 [/ yreturn 0;
7 u: e, a! d/ |- y& I}
6 n- p3 w1 y# x2 L
参考答案
本题很简单了。这个程序的潜在问题是,如果用户输入了超过80个长度的字符,那么就会有数组越界的问题了,你的程序很有可能会crash了。
! [2 v. O4 {( u) o, n% A
7
请问下面的程序输出什么?
) L1 n7 c5 u' f. d8 x/ X- s
#include<stdio.h>
7 d& Y+ H0 X4 r( I7 }7 rint main()$ c7 O8 q# F9 S0 Z! ~8 H/ J
{/ W' ~" R$ c. x3 H) _: ]# D. z
int i;
1 A: W/ @) W$ I( L$ k- H9 ~i = 10;" A+ @0 F+ M9 d, H! t5 p0 Q' N
printf("i : %d\n", i);
) k6 o1 d! u% Oprintf("sizeof(i++) is: %d\n", sizeof(i++));
1 t8 {, H  P  iprintf("i : %d\n", i);: A3 H) U& y7 `) p
return 0;! X4 n, _: X6 a0 M& _
}
; w# [! V7 x, t0 G
参考答案
如果你觉得输出分别是:10,4,11。那么你就错了。
错在了第三个,第一个是10没有什么问题,第二个是4,也没有什么问题,因为是32位机上一个int有4个字节。但是第三个为什么输出的不是11呢?居然还是10?原因是,sizeof不是一个函数,是一个操作符,其求i++的类型的size,这是一件可以在程序运行前(编译时)完全的事情,所以,sizeof(i++)直接就被4给取代了,在运行时也就不会有了i++这个表达式。

! C$ C/ J" l: f" g$ G* q2 V. ^$ k2 d
8
下面的程序的输出值是什么?

! y# Y7 S+ y8 e& J7 e
#include<stdio.h>( _! }6 v+ `, h* h8 i
#define SIZEOF(arr) (sizeof(arr)/sizeof(arr[0]))" _& a( o) j! ?0 x, w( f: W
#define PrintInt(expr) printf("%s:%d\n",#expr,(expr))6 }* P/ D* [9 P" a, u+ ^; b/ C
, n( ^( D1 Y% W3 `
int main()  e) p% O* Q9 E. G0 Z( S
{
7 d+ m' L# s& n% p6 p3 d/* The powers of 10 */& s, |, y1 w$ D+ c. W! e
int pot[] = {
- X6 V+ t) i9 i0 C- ]0001,7 ~5 Z( g% R0 l% ]2 Z, ~* m$ h9 b
0010,6 p% L$ Q# o% R3 }' {3 R  t
0100,8 M( j/ o5 P: O! l9 s3 l
10005 c2 ^6 N9 F) N1 r, _  o
};
; \. t/ {4 s+ G: s4 fint i;
9 f  l/ x3 m: b5 B1 y" [9 r  z) yfor (i = 0; i < SIZEOF(pot); i++)PrintInt(pot);4 d  ?$ n* j$ b
return 0;2 C, ?) [7 t8 r" d2 J
}. x( X/ V( J& H7 g% h0 ?  l9 \
参考答案
如果你对于PrintInt这个宏有问题的话,可以去看一看资料。不过,本例的问题不在这里,本例的输出会是:1,8,64,1000。其实很简单了,在C/C++中,以0开头的数字都是八进制的。

* i3 @, Z* F. r7 h- V& h
9
下面的输出是什么?

1 B  L0 ?- [5 ^; U. B6 S& h' w* c6 d. i
#include<stdio.h>$ u6 h) v) n/ r
int main()
; e/ L) `% f/ f7 f& L{
% [. N$ c' D: \+ jint i = 6;* ^: s$ D6 Y. c" i
if (((++i < 7) && (i++ / 6)) || (++i <= 9));9 n- z, c. L- ^3 h7 F! |. o9 z
printf("%d\n", i);
( g: Z6 z1 l6 O" p. l( K" Areturn 0;0 u. K1 K& I5 C  W
}, j+ H6 P! ?. T5 J4 P8 ^/ e
参考答案
本题并不简单的是考前缀++或反缀++,本题主要考的是&&和||的短路求值的问题。
所谓短路求值:对于(条件1 && 条件2),如果“条件1”是false,那“条件2”的表达式会被忽略了。对于(条件1 || 条件2),如果“条件1”为true,而“条件2”的表达式则被忽略了。
所以,我相信你会知道本题的答案是什么了。

6 P0 O# ~/ Q- f# @; U  p
10
下面的C程序是合法的吗?
1 U5 f4 v  W5 e; W  F
#include<stdio.h>: K- I2 x2 f, t, C5 f* M' Z
int main()
  Y) y: i% c. B1 F% j{
7 x* A4 D5 Z) K0 A8 i6 @) d6 Sint a = 3, b = 5;
9 K% q$ D. o* Q, ^0 @, r; K9 [2 eprintf(&a["Ya!Hello! how is this? %s\n"], &b["junk/super"]);- Z% k" @& D# M6 U
//等价printf("Hello! how is this? %s\n", "super");; N% C8 i! j& [6 I( f
printf(&a["WHAT%c%c%c %c%c %c !\n"], 1["this"], 2["beauty"], 0["tool"], 0["is"], 3["sensitive"], 4["CCCCCC"]);9 x; O( f* P+ Q9 `8 D. G+ E
return 0;
  l6 C7 C! Z) l1 g/ O: z}
) A2 M( ^: N6 P/ X! Y8 r( @- {
参考答案
本例是合法的,输出为:"Hello! how is this? super That is C !"
本例主要展示了一种另类的用法。下面的两种用法是相同的:
  • "hello"[2]
  • 2["hello"]
    + a* F8 q' _# G
如果你知道:a 其实就是 *(a+i)也就是 *(i+a),所以如果写成 i[a] 应该也不难理解了。

/ Q- }( p; s  A% ^
赞 收藏 评论0 发布时间:2020-10-12 22:46

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版