试题主要考查面试者对宏定义的使用, 宏定义可以实现类似于函数的功能, 但是 它终归不是函数,而宏定义中括弧中的"参数" 也不是真的参数,在宏展开的时候对 "参数" 进行的是一对一的替换. 程序员对宏定义的使用要非常小心,特别要注意两个
问题: (1)谨慎地将宏定义中的"参数"和整个宏用用括弧括起来.所以,严格地讲,下述
解答: #define MIN(A,B) (A) <= (B) ? (A) : (B) #define MIN(A,B) (A <= B ? A : B ) 都应判 0 分; (2)防止宏的副作用. 宏定义#define MIN(A,B) ((A) <= (B) ? (A) : (B))对 MIN(*p++, b)的作用结果是: ((*p++) <= (b) ? (*p++) : (*p++)) 这个表达式会产生副作用,指针
p 会作三次++自增操作. 除此之外,另一个应该判 0 分的解答是: #define MIN(A,B) ((A) <= (B) ? (A) : (B)); 这个解答在宏定义的后面加";" ,显示编写者对宏的概念模糊不清,只能被无情地判 0 分并被面试官淘汰. 试题 4:为什么标准头文件都有类似以下的结构? #ifndef __INCvxWorksh #define __INCvxWorksh #ifdef __cplusplus extern "C" { #endif /*……*/ #ifdef __cplusplus } #endif #endif /* __INCvxWorksh */ 解答: 头文件中的编译宏 #ifndef __INCvxWorksh #define __INCvxWorksh #endif
的作用是防止被重复引用. 作为一种面向对象的语言,C++支持函数重载,而过程式语言 C 则不支持.函数被 C++ 编译后在 symbol 库中的名字与 C 语言的不同.例如,假设某个函数的原型为: void foo(int x, int y); 该函数被 C 编译器编译后在 symbol 库中的名字为_foo,而 C++编译器则会产生像 _foo_int_int 之类的名字. _foo_int_int 这样的名字包含了函数名和函数参数数量及类型信息, C++就是考这种机制来实现函数重载的. 为了实现 C 和 C++的混合编程,C++提供了 C 连接交换指定符号 extern "C"来解决名字 匹配问题,函数声明前加上 extern "C"后,则编译器就会按照 C 语言的方式将该函数编译为 _foo,这样 C 语言中就可以调用 C++的函数了. 试题 5:编写一个函数,作用是把一个 char 组成的字符串循环右移 n 个.比如原来是 "abcdefghi"如果 n=2,移位后应该是"hiabcdefgh" 函数头是这样的: //pStr 是指向以'\0'结尾的字符串的指针 //steps 是要求移动的 n void LoopMove ( char * pStr, int steps ) { //请填充…… } 解答: 正确解答 1: void LoopMove ( char *pStr, int steps ) { int n = strlen( pStr ) - steps; char tmp[MAX_LEN]; strcpy ( tmp, pStr + n ); strcpy ( tmp + steps, pStr); *( tmp + strlen ( pStr ) ) = '\0'; strcpy( pStr, tmp ); } 正确解答 2:
void LoopMove ( char *pStr, int steps ) { int n = strlen( pStr ) - steps; char tmp[MAX_LEN]; memcpy( tmp, pStr + n, steps ); memcpy(pStr + steps, pStr, n ); memcpy(pStr, tmp, steps ); } 剖析: 这个试题主要考查面试者对标准库函数的熟练程度, 在需要的时候引用库函数可以很大 程度上简化程序编写的工作量. 最频繁被使用的库函数包括: (1) strcpy (2) memcpy (3) memset 试题 6: 已知 WA