我是一匹静静奔跑的骏马\r\n ~~~~~~~~~~~~~~~~~~~\r\n in doing we learn!\r\n ~~~~~~~~~~~~~~~~~~~\r\n

面试题 C

上一篇 / 下一篇  2007-09-07 13:55:41

8?,Zm V reR0嵌入式开发.C语言面试题LUPA开源社区8Y-E0|L\1eZ
预处理器(Preprocessor)LUPA开源社区4g2O}%Z;I0?7SK

{r"E1e#x%M7aUG01. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)
:tU)VZ1sV0#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
T&q G7i.PGTn&Ns0我在这想看到几件事情: LUPA开源社区]'g&O'mVA([N
1). #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)
y5Pfh {l:wH4]02). 懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的。 LUPA开源社区!R4o)L9Y ds c m&g
3). 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。 LUPA开源社区 p/@~Oj L Lr
4). 如果你在你的表达式中用到UL(表示无符号长整型),那么你有了一个好的起点。记住,第一印象很重要。
4t,u+XW @bO\0C++面试题集,C++面试答案,C++面试,C++试题,C++试卷

+s!f\3\N0

zD%j"~Bv{x#X02. 写一个"标准"宏MIN,这个宏输入两个参数并返回较小的一个。LUPA开源社区 o Q2{wf wy O py
#define MIN(A,B) (A<= B ?A: B)

(E^T bB3A0

,Zv3V;CP0C\C++试题集 C\C++ Development 这个测试是为下面的目的而设的:

wg-Nal r.H'R1@0

8Gg.Q8wM(H%~%~01). 标识#define在宏中应用的基本知识。这是很重要的,因为直到嵌入(inline)操作符变为标准C的一部分,宏是方便产生嵌入代码的唯一方法,对于嵌入式系统来说,为了能达到要求的性能,嵌入代码经常是必须的方法。
K[)x;A4C02). 三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生比if-then-else更优化的代码,了解这个用法是很重要的。
,]`9f$v:sv#D03). 懂得在宏中小心地把参数用括号括起来
`l"e#Z}k"jM04). 我也用这个问题开始讨论宏的副作用,例如:当你写下面的代码时会发生什么事? LUPA开源社区'Sk0_7s.P(qw9a
least = MIN(*p++, b);LUPA开源社区z/{G P#`vkS

J9Vn;F.lRD03. 预处理器标识#error的目的是什么?LUPA开源社区fN+m$x7Zn[3T+N

LUPA开源社区2K.oc _$nAs0w

    编译程序时,只要遇到 #error 就会跳出一个编译错误,既然是编译错误,要它干嘛呢?其目的就是保证程序是按照你所设想的那样进行编译的。下面举个例子:程序中往往有很多的预处理指令#ifdef XXX...#else#endif当程序比较大时,往往有些宏定义是在外部指定的(如makefile),或是在系统头文件中指定的,当你不太确定当前是否定义了 XXX 时,就可以改成如下这样进行编译:#ifdef XXX...#error "XXX has been defined"#else#endif这样,如果编译时出现错误,输出了XXX has been defined,表明宏XXX已经被定义了。用处就是这样,是不是感觉很没有用处

4o(`I~N N#Uq@EA7d+R0

seBd Xp/y4^6M0死循环(Infinite loops)

-{T;m-}{ |-P'yT0

:Jk!_+W3G)n a04. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?LUPA开源社区nm${&Zs1],Lk

BX3q l6D*R,ht0这个问题用几个解决方案。我首选的方案是: LUPA开源社区@&Ju ^7{6rR3c
while(1) { } LUPA开源社区v"`1RN},F VMBy
一些程序员更喜欢如下方案:
W'RA9~0X~P+K0for(;;) { } LUPA开源社区M M I b n
这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的
T!L&D2Mq1^.J0基本原理。如果他们的基本答案是:"我被教着这样做,但从没有想到过为什么。"这会给我留下一个坏印象。
%[&k#n3a E`UO0第三个方案是用 goto LUPA开源社区5Al-`(}M1D$D
Loop: LUPA开源社区:ga%i)Y&[(p
...
ejS7pH1K*LZ0goto Loop;
,m-S7uS8}W7L4J0应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。

4?"Y"z/ajl0

2C"s kl*z!r5CX }0数据声明(Data declarations) LUPA开源社区UDZ LiJ

LUPA开源社区Q#^1B3fjs1V

5. 用变量a给出下面的定义
J*s:Vz.g S0D_0a) 一个整型数(An integer) LUPA开源社区7zc+R R,\]n$m
b) 一个指向整型数的指针(A pointer to an integer) LUPA开源社区AL-d$M;J%B
c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)
qx,?2b1tw8ig1_TN0d) 一个有10个整型数的数组(An array of 10 integers) LUPA开源社区*uH-Xr&q8F[
e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)
n-C:p!l [h%mP,H0f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)
-D)xx5yO3Q7u:l"rBB~0g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer) LUPA开源社区 `pvn5B&h#] ]
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )
8nk+m$P~ JG2g0答案是: LUPA开源社区;XS(r h`T"b3b
a) int a; // An integer LUPA开源社区'E~hym sp-p#|7U
b) int *a; // A pointer to an integer LUPA开源社区] _'{A0b)h6gv;m}V
c) int **a; // A pointer to a pointer to an integer
;n`/uHD5A0d) int a[10]; // An array of 10 integers LUPA开源社区`4Z-z0aDF+i-Mq
e) int *a[10]; // An array of 10 pointers to integers LUPA开源社区 Z:V;T x qY
f) int (*a)[10]; // A pointer to an array of 10 integers
2qH*R;xzC3Z0g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
,P5oE+pf4lI}0h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer LUPA开源社区*vE9t-J.M _T%YF|;J

LUPA开源社区s5A U4zR l*e

LUPA开源社区l{Lk:}dtv0~
人们经常声称这里有几个问题是那种要翻一下书才能回答的问题,我同意这种说法。当我写这篇文章时,为了确定语法的正确性,我的确查了一下书。 LUPA开源社区K`q.{.gS
但是当我被面试的时候,我期望被问到这个问题(或者相近的问题)。因为在被面试的这段时间里,我确定我知道这个问题的答案。应试者如果不知道 LUPA开源社区vqk^ U!ie
所有的答案(或至少大部分答案),那么也就没有为这次面试做准备,如果该面试者没有为这次面试做准备,那么他又能为什么出准备呢?

T6Nz{#pv2w0

$^*}8o,l3@"Xr^0LUPA开源社区#~Lf9r J(M:UnB
Static

4mt(z6FyAZ1x2T(Q0 LUPA开源社区qt#P B#pfN'l[P

6. 关键字static的作用是什么?LUPA开源社区$z}(l S_7n7E+s

LUPA开源社区G;T.|J,p$P%ub,n

这个简单的问题很少有人能回答完全。在C语言中,关键字static有三个明显的作用:
9L.AiJ0h*h-K01). 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
9ENAK]02). 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。
YTilQy03). 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。
,Hc jS X@0大多数应试者能正确回答第一部分,一部分能正确回答第二部分,同是很少的人能懂得第三部分。这是一个应试者的严重的缺点,因为他显然不懂得本地化数据和代码范围的好处和重要性。LUPA开源社区AGvuty;z$^1r

LUPA开源社区"y'e_!P%X(Cd+tb6M

LUPA开源社区5o/G*s7ia}mrX ?
Const

]C+?ztNY4a0 LUPA开源社区h Q5P;pQTe!TO*u/b x

7.关键字const是什么含意? LUPA开源社区/i.G n#]/q|g
我只要一听到被面试者说:"const意味着常数",我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.
,{7i1gpP b2S4f0如果你从没有读到那篇文章,只要能说出const意味着"只读"就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)如果应试者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?

|G&w V`] _ t0

t#_"[F P?;kg7l0const int a;
6}.h1vI)T_|G(s0fA0int const a; LUPA开源社区J? y^ t}E
const int *a; LUPA开源社区O rla7X"i
int * const a;
M%i i)OhS]0int const * a const;LUPA开源社区/jVnGe#ZW

l{UMv0C0前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由: LUPA开源社区S}h&G4~0{,n
1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。)
WP6n.}N cN02). 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。 LUPA开源社区T#hqb{D/u
3). 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。

W'D vP&E!i4@/gP0

5JH8W4`+r#tS0Volatile

1u1Tg1ir6|Ps0

'h#M.E6dD8Z08. 关键字volatile有什么含意 并给出三个不同的例子。LUPA开源社区x0~b"[q5]]q

LUPA开源社区Gu`&zwn*d

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: LUPA开源社区"eBx ID_Y+iA
1). 并行设备的硬件寄存器(如:状态寄存器)
#e3KT%PmU`02). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
8` g wA(}03). 多线程应用中被几个任务共享的变量
OKBJ.b0回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。 LUPA开源社区&QA/V nh
假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
| d3AF7h!I*b(R01). 一个参数既可以是const还可以是volatile吗?解释为什么。
i0Y,W/_h02). 一个指针可以是volatile 吗?解释为什么。 LUPA开源社区*oXq,?O&H`#T
3). 下面的函数有什么错误:
7~$YL7o:k5o0int square(volatile int *ptr)
UX!` dD+`X0{C0{ LUPA开源社区b@%T+TD#j:C
return *ptr * *ptr; LUPA开源社区 w rZq+Z/u
}
-xPE0VV0下面是答案: LUPA开源社区Uh d3o,A4`*]5sU*F.X
1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。 LUPA开源社区p;j&f3{%fV6y
2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。 LUPA开源社区*q:ZX4RZ8? c p,mh
3). 这段代码的有个恶作剧。这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码: LUPA开源社区 R4LOP8tT(lL
int square(volatile int *ptr) LUPA开源社区w3EO(N#}'l!iH[
{
[D|8oP a0int a,b;
]0?JX$D!K0a = *ptr;
b8W`nba0b = *ptr;
L(KN1RFl]0return a * b; LUPA开源社区1f[4|H4Kj8P5`]
} LUPA开源社区5J+x'h)X.Cb`
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下: LUPA开源社区["yu(dp\O"|r$?-w
long square(volatile int *ptr) LUPA开源社区 g1EArmLx
{
;g#M| X5{:J]/\XA]0int a; LUPA开源社区 R5Vv-} ]?`
a = *ptr;
!W.qoHY6B3I'b{0return a * a;
C.Q6Xs m5`2^i0}LUPA开源社区^*W_ kg`e

LUPA开源社区?$C9@!lLx:osK

位操作(Bit manipulation)

3Yuv-Rk$A5u,sm0 LUPA开源社区6Up%g8w$F Q J0E

9. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3。在以上两个操作中,要保持其它位不变。LUPA开源社区2Ox a/vooH7uO4E U

C;^!bqR0对这个问题有三种基本的反应 LUPA开源社区9L)O7{C L m9q
1). 不知道如何下手。该被面者从没做过任何嵌入式系统的工作。 LUPA开源社区0Mn9ZA)d%d&G X,b~*b
2). 用bit fields。Bit fields是被扔到C语言死角的东西,它保证你的代码在不同编译器之间是不可移植的,同时也保证了的你的代码是不可重用的。我最近不幸看到Infineon为其较复杂的通信芯片写的驱动程序,它用到了bit fields因此完全对我无用,因为我的编译器用其它的方式来实现bit fields的。从道德讲:永远不要让一个非嵌入式的家伙粘实际硬件的边。 LUPA开源社区M*w$vXi|dku
3). 用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法,是应该被用到的方法。最佳的解决方案如下:
.cmj5gn%iww"n0#define BIT3 (0x1<<3) LUPA开源社区CWg*]+w W R~f
static int a; LUPA开源社区4~$T9Jb Y*J"F
void set_bit3(void)
Jfj1oMo#m0{ LUPA开源社区1oCbp1v%e6L4ZXR
a |= BIT3; LUPA开源社区zo/dm:d!Jd k/u H
} LUPA开源社区&h^'P\2L
void clear_bit3(void)
0GY+VB2y z+m"{Q)@C Za0{ LUPA开源社区2|2W@,BVa4CUR/r}N*c
a &= ~BIT3;
QtZaa9F3z v0} LUPA开源社区[P(l!s[ c F
一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数,这也是可以接受的。我希望看到几个要点:说明常数、|=和&=~操作。LUPA开源社区uc6A1~&R/R3m
10. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。LUPA开源社区A*A'O\|(D Ge

LUPA开源社区7}ZWd7h1zt"W

这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换(typecast)为一指针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下:
#md3k!q.Ne,G9W0int *ptr;
_Lg#cL,`0ptr = (int *)0x67a9;
jhuc}x Y4]zQ/F K0*ptr = 0xaa55;LUPA开源社区)Y'td)y1t

HmK-GYs0一个较晦涩的方法是: LUPA开源社区O:h1V0HWgMyfZUW
*(int * const)(0x67a9) = 0xaa55;

J1`.j)RD ?&S0

z C Tk@/g0即使你的品味更接近第二种方案,但我建议你在面试时使用第一种方案。LUPA开源社区jHBl0~4|2Q

Jk;`)O.fm8n0Z0中断(Interrupts) LUPA开源社区Az9I2x\m

dT'\FB/L/M^3K011. 中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展—让标准C支持中断。具代表事实是,产生了一个新的关键字__interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。LUPA开源社区{!Xi6CX!y{0u

LUPA开源社区"p$_!Co$R'Y~

__interrupt double compute_area (double radius)
C2AYH/c'l-F0{
p9`+JTOl%j0double area = PI * radius * radius;
zZ0Ou)O6Lm0printf(" Area = %f", area); LUPA开源社区,x1_"RjXU
return area;
t2h6_ K-b]O4te0}

&e`#@j4v-?0 LUPA开源社区@#P;[ppR

这个函数有太多的错误了,以至让人不知从何说起了: LUPA开源社区/J$h7RR{l ~B|d,a9qq
1). ISR 不能返回一个值。如果你不懂这个,那么你不会被雇用的。
vEd TxV YM02). ISR 不能传递参数。如果你没有看到这一点,你被雇用的机会等同第一项。
2Q$a5t Z L)F03). 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的。 LUPA开源社区)Ba.qyZ2K ]7i
4). 与第三点一脉相承,printf()经常有重入和性能上的问题。如果你丢掉了第三和第四点,我不会太为难你的。不用说,如果你能得到后两点,那么你的被雇用前景越来越光明了。

n~\c'H9\%B0 LUPA开源社区Ma9fb} {vG

代码例子(Code examples)LUPA开源社区_o{vO!~5YG
12 . 下面的代码输出是什么,为什么?

_iHc D9W0 LUPA开源社区YL Y_hks

void foo(void) LUPA开源社区1o(Rs)}}6f
{ LUPA开源社区FBd4rm b
unsigned int a = 6;
zW7p9A8k_6E0int b = -20;
K['V|r0(a+b > 6) puts("> 6") : puts("<= 6"); LUPA开源社区UYX U oOs,^
}

jP [U*x6GTTG,b2I0

S1vO.dG"@0KT b0这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。 因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。LUPA开源社区k+y*j `$~O

4T/C9m!no%w/?-gI013. 评价下面的代码片断:LUPA开源社区M8G*gIe6d

LUPA开源社区5y L:L])^-q"p_

unsigned int zero = 0; LUPA开源社区;US[]Y9g e
unsigned int compzero = 0xFFFF; LUPA开源社区S:]WY z%O)_Z1F
/*1's complement of zero */

RGjg'V0 LUPA开源社区EP*KX6f.g wr

对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:

9u,rIJB$@/cN0

}7i1b#yh0unsigned int compzero = ~0;LUPA开源社区W't,Vp_!E0dZ!T#^

LUPA开源社区6rPO8JB&A

这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里,好的嵌入式程序员非常准确地明白硬件的细节和它的局限,然而PC机程序往往把硬件作为一个无法避免的烦恼。 LUPA开源社区$Lj ^2[ M}Xn
到了这个阶段,应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是很好,那么这个测试就在这里结束了。但如果显然应试者做得不错,那么我就扔出下面的追加问题,这些问题是比较难的,我想仅仅非常优秀的应试者能做得不错。提出这些问题,我希望更多看到应试者应付问题的方法,而不是答案。不管如何,你就当是这个娱乐吧…LUPA开源社区7\)}*e)mzn

LUPA开源社区p+U-lj nx c

LUPA开源社区2lmIF,sh3w4n,yl
动态内存分配(Dynamic memory allocation)LUPA开源社区"_|!?slaz?

LUPA开源社区Ax+DB/X D GB


Y@UT#m1v014. 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?

O\G X Dz0 LUPA开源社区P%^c`f;C m#]Kh

这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。这个主题已经在ESP杂志中被广泛地讨论过了(主要是 P.J. Plauger, 他的解释远远超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!让应试者进入一种虚假的安全感觉后,我拿出这么一个小节目:下面的代码片段的输出是什么,为什么?LUPA开源社区|u{}qNph5U!|

A5Q)|*| z0char *ptr;
2\U2K3q,R {4Ph0if ((ptr = (char *)malloc(0)) == NULL) LUPA开源社区;^rb aI{
puts("Got a null pointer"); LUPA开源社区&ZKFqst"M0b9I)F
else
Y|L!ai/E0puts("Got a valid pointer");

jn;e}#]X[ T2|0 LUPA开源社区.h+F*L l|\1q Va#U7DL D'T

这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。这就是上面的代码,该代码的输出是"Got a valid pointer"。我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。LUPA开源社区dB-y6h2B*Rr@

-K0B"a`d!f S0Typedef LUPA开源社区$f.R9h&@t

E%Mt-C F.m2A015. Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子: LUPA开源社区u'E0Axa \r
#define dPS struct s * LUPA开源社区H0aM*p C"|u4B
typedef struct s * tPS;

bHBB U5]_-Wd2}0

fI)QCA!N0以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?(如果有的话)为什么?
[4V$@(oYG0这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。答案是:typedef更好。思考下面的例子:
:aRFIO&dz0dPS p1,p2;
6tZ&`Vp-g|0tPS p3,p4;LUPA开源社区#Yj c(CtFt

LUPA开源社区'xVl-Rx}

第一个扩展为 LUPA开源社区5E![%F@*_#SQG
struct s * p1, p2;

7R HIm[QO0

9A \"|5MK @9?0u0上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。第二个例子正确地定义了p3 和p4 两个指针。

a _,R(pPN{*J*n/ec0 LUPA开源社区"f&Q~X)N[7_&K

晦涩的语法

.M`VLJ0

&r x/E4IeT^ f1b.E016. C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么? LUPA开源社区,ww&W]#N(^%Z:Q
int a = 5, b = 7, c;
5y3Q:A&}b3}"O+T0c = a+++b;

9Vu'_vQ0

"s'Ty(whEk7_$qu0这个问题将做为这个测验的一个愉快的结尾。不管你相不相信,上面的例子是完全合乎语法的。问题是编译器如何处理它?水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。因此,上面的代码被处理成: LUPA开源社区0H0I7m:qQ
c = a++ + b; LUPA开源社区ru} N;KVAu'k
因此, 这段代码持行后a = 6, b = 7, c = 12。 LUPA开源社区H @-A |~ E1M
如果你知道答案,或猜出正确答案,做得好。如果你不知道答案,我也不把这个当作问题。我发现这个问题的最大好处是:这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题

[ u)[Nir T:n0

poc&^5n8vv.Q-]0What will print out?

p+Ade5z b:[0

6E&W xlGN~0main() LUPA开源社区8rN K`I h pz gi
{
8o;z8glKm0char *p1="name";
jgs(I:z#E'R n0char *p2;
*T2wSdBv0p2=(char*)malloc(20); LUPA开源社区pJ*hK,UQCDK
memset (p2, 0, 20); LUPA开源社区@d;ih `-D4S'or
while(*p2++ = *p1++); LUPA开源社区,{O q3} inu#sl
printf("%s\n",p2); LUPA开源社区]:`!l1x/WET

LUPA开源社区k]!n? {p0U%[

}

R;cJ$M5c0 LUPA开源社区UT]&c @b }Vr

Answer:empty string.

!R}yoXV.} @0

'VJr*IM+m*@+O0What will be printed as the result of the operation below:

NY8?#IB0 LUPA开源社区M7{gaMd

main()
-L^|WUJ._ i)g9fS\&t0{
%|~R?ec'@0int x=20,y=35; LUPA开源社区.F;[4l0M$e,s{o_ A
x=y++ + x++; LUPA开源社区7~/X-V+i`tx
y= ++y + ++x;
s{ m!X(wTP Te0printf("%d%dn",x,y); LUPA开源社区%X`5G;ZK"CiB D
} LUPA开源社区7L@/_"F1P ky`"r

lb6a#|/H'@ _:z0Answer : 5794

@"Ns&z){W0M!Cd0

:W8N"BqkCW0What will be printed as the result of the operation below:LUPA开源社区&IX.tJ] jLK|k

LUPA开源社区*] BVbI9K4S Ej

main()
!i0CM7ykvN~m0{ LUPA开源社区9G:}:} y4v`#`8D Q$tv
int x=5;
O w7t([F(u0printf("%d,%d,%dn",x,x< <2,x>>2); LUPA开源社区$_)ng m4cW"\&D
}

BG R6F1Ta0 LUPA开源社区T sB x%|O ~4M;V#}.?H

Answer: 5,20,1

p7qa/hE ~1J Y0

,Z6_,jC0dJf9t0What will be printed as the result of the operation below:

1\;G FQ)y)|0

T(l#\f1h2@$m:x0#define swap(a,b) a=a+b;b=a-b;a=a-b; LUPA开源社区%w c9]+I^`$ze
void main()
hX6PE i$U5I$x0{ LUPA开源社区IO$i&S+|%sS
int x=5, y=10;
sp^;`ex-^A0swap (x,y);
,f)C"q{5o0printf("%d %dn",x,y); LUPA开源社区(zB|+?q%J
swap2(x,y);
Q3U3Q0?h9@v.f0printf("%d %dn",x,y); LUPA开源社区8y:w%z"K/X%H,L`
}

HH*\GDu3H6C]0

@~.x6D$B2yc-[8o%o8?0int swap2(int a, int b) LUPA开源社区6^r:K(V!UCq3k
{ LUPA开源社区 [4_ZCkB
int temp;
p7UQ)t2XQ0temp=a;
9{p$TG XP0b=a;
`R5Y RMJJ g-aB.x5Si0a=temp; LUPA开源社区;g"x`%i!d]s'wh$ss
return 0; LUPA开源社区'Oh:{#g*?^

L i^~F A7p0}

j&y[0xLQ,GZbZ0

2l5Am;fjFx0Answer: 10, 5
4s4E&o3`l {1bs"F010, 5 LUPA开源社区F)y"p`(]z3x5s5T

LUPA开源社区.AbZ(yD:K

What will be printed as the result of the operation below:

dz0RASi6{t(FS[0

+C(TP3^M(V0main()
%L}P&kp,I0{ LUPA开源社区]bS"]H jM
char *ptr = "Cisco Systems"; LUPA开源社区jV _ b,^#Jq
*ptr++; printf("%s\n",ptr);
W&Kr vd6f7]C0ptr++; LUPA开源社区W$n0jU_L
printf("%s\n",ptr); LUPA开源社区N"Y7Y)D%r'^*OC {
}

(q HZ1rU!G.M0

$c-e8TbH/Fl[0Answer:isco Systems
I4W1Rg^ K^0sco Systems

J*i_+s$|rY/}/Fs0

?'S r$Q|`*v0What will be printed as the result of the operation below:

4u#qD9SDAH?0

-|dL2]:z t}.O0main()LUPA开源社区9n#XB Zl'S9T
{ LUPA开源社区o9L g hVBuo
char s1[]="Cisco";
&u:@yP}1a!J~(HG0char s2[]= "systems"; LUPA开源社区Rjp1G&f%G
printf("%s",s1); LUPA开源社区elW-B1N9_
}
,YS@9];TH pL.s0Answer: Cisco LUPA开源社区[,l"k(ouN3S

LUPA开源社区E.u h U B'\;L-vd

What will be printed as the result of the operation below:LUPA开源社区tS.q ?a2k%y

,W)f;?(i8Q8A0main()LUPA开源社区0U C2TC-NU8k
{ LUPA开源社区LPn\somB D
char *p1; LUPA开源社区n/Y7x J,_Y:U:fuT'k_
char *p2;
T vC8[8f z0p1=(char *)malloc(25); LUPA开源社区:mK#h1I:Z#H K3Tx[f'q
p2=(char *)malloc(25); LUPA开源社区}'|0go3b_;?b

9O8qb x#gt!GU6W0strcpy(p1,"Cisco");
-n.Yv0`#S3V|(W0strcpy(p2,"systems");
;d)p] qO0cL0strcat(p1,p2);

4?/g5z]q*Sd et0

[ U rL Jm/s5D"y0printf("%s",p1);

R?:KM)Q0

M$B&c4c&VuVTA,b0} LUPA开源社区C+@-dvZ;O P

a H,RaP*y0Answer: Ciscosystems

,o+hw`:X'X aI s5R0 LUPA开源社区 E^J]#UjZOc&} b

The following variable is available in file1.c, who can access it?:

JYG?.~Z1dc/r0 LUPA开源社区G&JOe'j

static int average;LUPA开源社区#i{)HqgqV)H;s-}g

LUPA开源社区TMln7x f4B#H-X

Answer: all the functions in the file1.c can access the variable. LUPA开源社区F:p6[{+d5~#Xr

LUPA开源社区Q(MY%H.v?

WHat will be the result of the following code?

&os.^ XX,G0

Y$V v0XB'ZG\0#define TRUE 0 // some code LUPA开源社区da-`M/FTo#j n3qm
while(TRUE)
y9Oy2KBk!}#gb0{ LUPA开源社区Qh$?;['XZ8{w@%S

LUPA开源社区9h/Cz1pwO

// some code LUPA开源社区0Tu,i!G5Hg+hE&I ^

m Yi*b5|8uC%vU`b0}

gH$I0V!x'^5?0

aE4^{;? sI g0Answer: This will not go into the loop as TRUE is defined as 0.

e&dA[4rt#T0

Ui2UZd UG3F*rP0What will be printed as the result of the operation below:LUPA开源社区fKb)H4L{.{7}

C2_2P1g#f2@0int x;
aAM3r9Le/f u0int modifyvalue() LUPA开源社区WU*K9D5E!g?4\U%I
{
ZU/W:y7i?3l0return(x+=10);
j[&yn+N-y0}
,hM:y$]?i0int changevalue(int x)
q.a2z F E&b!h0{
X1v&xs RQBB0return(x+=1); LUPA开源社区u } Yn;M6dTgx7|7G
}

(P v5|)A"p.u/A*p0

s-v&{(K g"z|0void main()LUPA开源社区dy3]QH \6Bi b2\
{
E/T#Mu{'Z"y0int x=10;
Z|1g%L/A`t i0x++;
E d;J1i]Q9Xy0changevalue(x);
@t GicV+u8? Bz B0x++;
v A$zB [0modifyvalue(); LUPA开源社区 ^W9g9k*]m'U
printf("First output:%dn",x);

kjX F0C%s-pvC0 LUPA开源社区 u h`.[@#oy"^2v'j

x++; LUPA开源社区d p;] G(Y
changevalue(x); LUPA开源社区2i${iO WP.l
printf("Second output:%dn",x); LUPA开源社区Y,]r&]1AQ
modifyvalue();
r-\C'QV!A0printf("Third output:%dn",x);

#?:f3Ukx7G+g,dR0

'^%];|g h6U&[ r;Q@0} LUPA开源社区*f` {YJY"c q

LUPA开源社区DUa{Z\d3\

Answer: 12 , 13 , 13

$B6Nq#M b-Xv.|0

Z"~ j Po0L"IP F0What will be printed as the result of the operation below:

%a5?*W9E$s~0

nsi:vH+E9g0main()LUPA开源社区PC0f:mpN
{
.P6bIn2z Gl0int x=10, y=15;
M]N"UV1X0x = x++; LUPA开源社区+q{h+F0T7G4W
y = ++y;
2Rq1@~x0printf("%d %dn",x,y); LUPA开源社区3Z)He Bq7?bH
}

j%~ xDpYgnJ(w)]0 LUPA开源社区N;ka,T7x

Answer: 11, 16

X9i+T9A$cH0 LUPA开源社区 g(j;XV/E,` m(c w

What will be printed as the result of the operation below:

On?wcg \CX0

h3~+I Q"G(o&qZ0main()LUPA开源社区0@*bt)^ g{
{
&?~JN"\0int a=0;
uo"zm vskX0if(a==0)
5` p:db2M R0printf("Cisco Systems\n");
:c~nV*fQ0printf("Cisco Systems\n");
8ENP7ixq0}

&_.J:[8gJI X0 LUPA开源社区#A7d-q!dmB-c(P

Answer: Two lines with "Cisco Systems" will be printed. LUPA开源社区MP|9[cm

]Uc/gn"^ t-r0LUPA开源社区O K V!W1A pk
简答题LUPA开源社区!XKyAF"b
1、头文件中的 ifndef/define/endif 干什么用?

B^L],\#l0

'i6O;W!q%c(lv$lZ0答:防止该头文件被重复引用。LUPA开源社区 [*wA_7r0o5~1^

]o.p'| ?yQb02、#include <filename.h> 和 #include “filename.h” 有什么区别?LUPA开源社区n2p`4[I[w

LUPA开源社区,yoMck']

答:对于#include <filename.h> ,编译器从标准库路径开始搜索 filename.hLUPA开源社区W VJ5\NP

LUPA开源社区e(PvS*sJ$|:pQ

对于#include “filename.h” ,编译器从用户的工作路径开始搜索 filename.hLUPA开源社区&p(xU%@_MA

1~GvLd&G!_2tr0LUPA开源社区7B&Wuu.dL
3、const 有什么用途?(请至少说明两种)LUPA开源社区+C4K'q+Q7l;E\ _

4?u$y)`iu"M0答:(1)可以定义 const 常量

*xCu)P7Z0

zN$T.Bh6]!S0(2)const可以修饰函数的参数、返回值,甚至函数的定义体。被const修饰的东西都受到强制保护,
1q9y6\@2`'S0可以预防意外的变动,能提高程序的健壮性。

Hd6D(M] aEOX0 LUPA开源社区.oE!O5lPWY8x

LUPA开源社区a6^ J4V TL#@0O`)hR#`A
4、在C++ 程序中调用被 C编译器编译后的函数,为什么要加 extern “C”? (5分)

S{zMs"x0

Y hj)ec5HTwv0答:C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。
zs@W o0假设某个函数的原型为: void foo(int x, int y);

3jf,EDn|9kl-w0 LUPA开源社区Uh"y&[;[6k1l

该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。LUPA开源社区 @3R4ewI pq3}

,Nd G {s S%VQ:D e0C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。LUPA开源社区;m.L0DQ6Dn!z0_pd

LUPA开源社区b#e3v%@Nl N)j h6GMKR

5 已知strcpy函数的原型是LUPA开源社区#[uMq{]k4kv

u$T'bVQ;j"e0char *strcpy(char *strDest, const char *strSrc);

`p |9W1I;`$bv0

e6m IL0sr u9F:o lS m0其中strDest是目的字符串,strSrc是源字符串。

g3iD,x9hsU[0

d6S#Ua%nl0(1)不调用C++/C的字符串库函数,请编写函数 strcpyLUPA开源社区Y } y X&S:x!`,Qt*f

LUPA开源社区9zbl$fXa

char *strcpy(char *strDest, const char *strSrc);LUPA开源社区8M/w/eGb,T

Pva m X0{LUPA开源社区1pR/[.Y@*K){M

LUPA开源社区yv)\$N#XC7T0]

assert((strDest!=NULL) && (strSrc !=NULL)); // 2分LUPA开源社区:?}q!a7V n0ae

LUPA开源社区1b&h,?z,jsl#R

char *address = strDest; // 2分

/k,g)s(hlX:yUn0

w \)m)wN,d;cy0while( (*strDest++ = * strSrc++) != ‘\0’ ) // 2分LUPA开源社区 ["b2|5LH/z j+X

!A^ [tR.yl0NULL ; LUPA开源社区t ?&uK&s~B du

;C;q LC9p0return address ; // 2分LUPA开源社区;s:u(D7f$j,Jo

5o:G)]3i | i(Mb0}LUPA开源社区6^z3l,K%d7l4eY&b']"N+b

LUPA开源社区8K;j%ys;fg;\3B9D1R

LUPA开源社区]$cq"n7x
(2)strcpy能把strSrc的内容复制到strDest,为什么还要char * 类型的返回值?

mQ"?-U gT0

%shT@{:XL5ez V&Uj0答:为了实现链式表达式。 // 2分LUPA开源社区+z[~(emz0K

Ow6Z9_ xgE0例如 int length = strlen( strcpy( strDest, “hello world”) );LUPA开源社区xF[qJ]Y1cl

w+E8H1P,|0 LUPA开源社区fD7z4n%]-c)F

LUPA开源社区#me8|;b_T0a'{!E

class string
ji2y&?5yB0{
$BVE(Y t2T3?m]0 public:
;p!T'FE?/I)l| _0  string(const char *str = null);   // 普通构造函数
pljh(eQ6iG0  string(const string &other) ;     // 拷贝构造函数LUPA开源社区|`+MFR!tK
  ~string(void);                    // 析构函数
7n%H]L(]D0  string & ōperate =(const string &other);  // 赋值函数LUPA开源社区!K(yp1E8G w
 private:
fiJy xJ0  char *m_data;                   // 用于保存字符串
F\gZG#WGqur-x0}

x]:e$hG5G3wCT0 LUPA开源社区r#IW A0Sp!z ?

string ~string(void)
$i4d5jJL_0{
/S N5c^"_^0 delete [] m_data;         // 由于m_data是内部数据类型,也可以写成 delete m_data;
+N,{ob%R ~0}LUPA开源社区H5_ `a E u%o:f

LUPA开源社区C`%e Pbk2wf

                                                      LUPA开源社区8Jhr0x/U*FS
// String的普通构造函数 LUPA开源社区 ~m5w~I#Ai
string::string(const char *str )
g N L ?0g{1L5v0{
b`Iy I9E0 if(str == null )LUPA开源社区 G3TK8a0@
 {LUPA开源社区fbb3h{
  m_data = new char[12];
pK s }hXf*o$V.dB0  *m_data = '\0';
p#u+I4@zP wr0 }LUPA开源社区)ew?+b-u
 else
KF0^Ucp rjV0 {
zz5}'yNS0  int lenth = strlen(str);LUPA开源社区%vZ1V-w6N$Z"a
  m_data = new char[lenth +1];
?'yH2d3W pKr0  strcpy(m_data,str);LUPA开源社区"pwi%A#f_V
 }LUPA开源社区?6S?2qb)g ~$k
}LUPA开源社区"E$i.?$~3U[ e f\

LUPA开源社区(TXH-aP5QS,~

// 拷贝构造函数LUPA开源社区 ISR!Q%ND^
String::String(const String &other)LUPA开源社区`JbnW`3nj

LUPA开源社区ozt.ET^

{ LUPA开源社区]@(t#| ^!s's\9x8Rq
    int length = strlen(other.m_data); LUPA开源社区'N(D~*W"B? {
    m_data = new char[length+1]; LUPA开源社区K V~4g|]`
    strcpy(m_data, other.m_data); LUPA开源社区lJx7[2H

LUPA开源社区[#jq;Uer6C?

}

zI8o,v!k0 LUPA开源社区2a'j}'Q,@p*D@

// 赋值函数LUPA开源社区Iv1b kYU`
string & string::operate = (const string &other)LUPA开源社区~#]HkR.N v.D%o
{
*D0b^,r6t-V+xq0 // 检查自赋值 //
Sy&e9Q@0 if(this == &other)
#R6B-]n8\s0 {LUPA开源社区(k7x"Iu.k;{x
  return *this;LUPA开源社区4dX-w?(w!@
 }LUPA开源社区 {"^1o-D:V9?^wB
 // 释放原有的内存资源  
] D!u)^N7q7G0 delete [] m_data;LUPA开源社区j^&\-Ub
 // 分配新的内存资源,并复制内容
f8\RXF @#MF yt~0 int lenth = strlen(other.m_data);
dwe!OM9Mk)M0 m_data = new char[lenth+1];LUPA开源社区 v Z|!V)t&t I^
 strcpy(m_data,other.m_data);LUPA开源社区N? G}AD!CUV9B;A*g
 //返回本对象的引用 LUPA开源社区"A ]@+^;O
 return *this;LUPA开源社区^'^AV1Z `"H
}LUPA开源社区&[)\-}wR7eU

'` V7L.X4_j@,HV0 LUPA开源社区-@ [|K`1`V;RK-].J1e"Y

LUPA开源社区J;h5s,v&Qfts*^

1
"@(F^ WP&g4I[0void GetMemory(char *p)LUPA开源社区aBTXLdP
{LUPA开源社区K)X6g4T'N8HY:Qw
    p = (char *)malloc(100);   //栈指针分配动态内存,函数结束时自己释放
C:X {btI~ f j'o0}LUPA开源社区5W?7s)a f"}8s

6fe{(kCp|4^p)x0void Test(void)
Lh!S7j| D~0{
U7Ey:`*J0    char *str = NULL;LUPA开源社区:d-{o,oOT[
    LUPA开源社区a][#_ hzGf
    GetMemory(str);         //将NULL传给了函数,返回后还是NULLLUPA开源社区:E;a z*X C
    LUPA开源社区8S:LL!m*CXj
    strcpy(str, "hello world");     //将字符串拷贝到指向NULL的指针,出错
b S*s&sJ,zd0   
&sX}S/CQ0    printf(str);LUPA开源社区0nJ+L6?O9o:v
}

_F)j1Ut_0

N]e"T,x*m8N A0LUPA开源社区;t"qim[ v [L#My
请问运行Test函数会有什么样的结果?LUPA开源社区E8Ap8f'zd2a

\zTcXg"@ x3h0答:程序崩溃。LUPA开源社区#d$l-yjk^%fG#`

'{@&h-ja2tMo0因为GetMemory并不能传递动态内存,LUPA开源社区4}A"EA;NN;QP

\a#R5E }%{u0Test函数中的 str一直都是 NULL。

)| xjg:fM,Js"DqA0

[_o3[!H*[j M |0strcpy(str, "hello world");将使程序崩溃。

D rO `3]%{S.qX0 LUPA开源社区E JF/WG_+J

2
s G.o.` n7Jq0char *GetMemory(void)LUPA开源社区3s$jZV b)` L b-T2`B
{ LUPA开源社区4FW U6Tt4b tG$` r
 char p[] = "hello world";     //局部变量,栈指针指向常量LUPA开源社区uV;TPgui
 return p;                    //返回时栈指针释放
A'bH-H*_3B"Ml0}
`NjdRS w l k0void Test(void)LUPA开源社区 }W0s7R.Ht
{
6_eAjQ:U q0 char *str = NULL;           //局部变量指针LUPA开源社区9O6n4a*M,}&b(B.T#gl2C
 str = GetMemory(); LUPA开源社区 Gr B'V B;W$Uw7z
 printf(str);
1fu ?*D-a9_0}

4p7Z t CS j0 LUPA开源社区 e:N8r]$c5A-`W

请问运行Test函数会有什么样的结果?

%wH*J3Pk/B}8} iJ0 LUPA开源社区T&z&Vi$\Jn

答:可能是乱码。但也可能是hello world(如果栈地址没有被覆盖)LUPA开源社区e f$~d\

5W3d"BwJ0因为GetMemory返回的是指向“栈内存”的指针,该指针的地址不是 NULL,但其原现的内容已经被清除,
qJ {/VQ"]0新内容不可知。LUPA开源社区+a@ y8Q;W h

LUPA开源社区 o ]0rs+w0Fh8x]

3
gN p(a|(tf(rr,Q&f.c0void GetMemory2(char **p, int num)LUPA开源社区8l"u1f%Q*C }I
{LUPA开源社区_7C&n Z,l} H c
    *p = (char *)malloc(num);LUPA开源社区;z)@-[z{!x"G,|8X I
}
5e7Vb!WX0void Test(void)LUPA开源社区*@G C }-?kQ
{
(qNP.\Bs o/` `BE^0    char *str = NULL;  
0I DFE @0    GetMemory(&str, 100);   LUPA开源社区 z b[`smU
    strcpy(str, "hello");    
(o:ii!d#O0? c-p0    printf(str); LUPA开源社区bu~XL
}

WF'cz0@J0

.G2JYQiF7Wb0请问运行Test函数会有什么样的结果?LUPA开源社区xk EI~N cuc Zt

LUPA开源社区+a;J;C{jf H7A

答:

PJ;h,OpzX0 LUPA开源社区U0Ao2wXJ#`4ev

(1)能够输出hello

x/H;n*R4VE zn5}0

ZFoY @9J d(?4Y0(2)内存泄漏,要加上free(str);

)PP Y:vN0 LUPA开源社区u|"FU8M7D;ox


v3D.b'h J3p04 
VHY~ qj0void Test(void)LUPA开源社区n G5{Ae A
{LUPA开源社区$p lhp#mnHbz
    char *str = (char *) malloc(100);   
(q Al3v{ZuMa c(L^0    strcpy(str, “hello”);    LUPA开源社区xe+e HU$a7vQ(Ok
    free(str);       //内存已经释放,但str还是指向同一地址
AP!b h&K@7k/~0    if(str != NULL)  
h1sEc2qH SM0    {    LUPA开源社区T%VIG`(I
    strcpy(str, “world”);     //内存的内容被改变LUPA开源社区Q _Q%y'L
    printf(str);
.kM1u2c5R0    }
T6|NC+_g5Pi,P0}LUPA开源社区l r.t:?$]O'x6{5n

LUPA开源社区"V?HS4Ug-i

请问运行Test函数会有什么样的结果?

1Fg0s{h|%I0r,P0m0

$Oe8wtE f0答:篡改动态内存区的内容,后果难以预料,非常危险。
8T%va:]Q:r E;izfyV0因为free(str);之后,str成为野指针,
`'dw@4OR2F0if(str != NULL)语句不起作用。
#O W'O;{\"A0LUPA开源社区,}J^(eg ZQ0X

N qAe p6f i;d\N0
:xe{5s%f$x-n0

1UJ W3Z(i8V]n0O0

TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2008-10-12  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 7180
  • 日志数: 16
  • 图片数: 3
  • 文件数: 12
  • 书签数: 4
  • 建立时间: 2007-06-28
  • 更新时间: 2007-11-07

RSS订阅

Open Toolbar