1 错题
1.1 基础
1) 下列选项中,合法的 C 语言关键字是 D
A.VAR B. cher C. integer D. default
default 只用在 switch 语句中。
2) 若执行完成下列语句:
int a=3,b=6,c;
c=a∧b<<2;
则变量 c 的二进制值为:D
A.00011100 B.00010100 C.0001000 D.00011011
3) 设有以下定义或语句,则输出的结果是? A
(用 small 模式编译,指针变量占 2 个字节)
struct date
{long *cat;
struct date *next;
double dog;
}too;
printf("%d",sizeof(too));
A.20 B.16 C.14 D.12
4) 设 x、y、t 均为 int 型变量,则执行语句:x=y=3;t=++x||++y;后,y 的值
为 C
A.不定值 B.4 C.3 D.1
5) 执行下列语句中,sum 变量的值是:D
int sum=0
for(int i=0;i<10;i++,sum+=i);
A.45 B.55 C.0 D.编译错误
6) 请写出 float x 与“零值”比较的 if 语句:
【标准答案】 const float EPSINON = 0.00001;
if ((x >= - EPSINON) && (x <= EPSINON)
不可将浮点变量用“==” 或“!=” 与数字比较,应该设法转化成“>=”
或“<=” 此类形式。
7) 以下为 Linux 下的 32 位 C 程序,请计算 sizeof 的值。
char str[] = “Hello” ;
char *p = str ;
i nt n = 10;
请计算
(1)sizeof (str ) = (2)s i zeof ( p ) =
(3)sizeof ( n ) =
【标准答案】
(1)6、(2)4 、(3 )4
8) 请问以下代码有什么问题:
char* s="AAA";
printf("%s",s);
s[0]='B';
printf("%s",s);
有什么错?
【标准答案】"AAA" 是字符串常量。s 是指针,指向这个字符串常量,所
以声明 s 的时候就有问题。
cosnt char* s="AAA";
然后又因为是常量,所以对是 s[0] 的赋值操作是不合法的。
const char *p = "123";
p[1] = '3'; // 会报错
p = "456"; // 不会报错
const char * 只是说指针指向的内容不可变,但指针本身可以再赋值
假设你的程序是
char * findArg(char *s) {
return s;
}
这个时候,你如果传 const char *进去,那么好一些的编译器,会知道,你传
回的函数返回值,也是 const char *,也就是指针指向的内容不可写。
所以如果你传进去的是 const char *,最好还是把 char *name 写成 const char
*name,因为 char *name 可以对指针指向的内容进行修改。
用强制转换当然也可以,但是
const char *name2 = "123";
char *name = (char *)name2;
如果你对 name 指向的内容进行改变,如 name[2] = '4';
"123"是常量,对常量进行修改,你的程序就会发生不可预知的错误
char* findArg(char *){.....}
如果你这个函数,对传入的参数,不会对指针指向的内容进行修改,最好写
成 char * findArg(const char *) {....}
或 const char * findArg(const char *) {....}
9) 给定结构 struct A
{
char t:4;
char k:4;
unsigned short i:8;
unsigned long m;
}; 问 sizeof(A) = ?
【标准答案】8
10) struct name2{
char str;
int num;
short x;
}; 求 sizeof(name2)?
【标准答案】12
32 位 64 位
char 1 1
int 4 大多数 4,少数 8
short 2 2
long 4 8
float 4 4
double 8 8
指针 4 8
(单位都为字节)
结构体(struct):比较复杂,对齐问题。
联合(union):所有成员中最长的。
枚举(enum):根据数据类型。
(1)结构体变量中成员的偏移量必须是成员大小的整数倍(0 被认
为是任何数的整数倍)
(2)结构体大小必须是所有成员大小的整数倍,也即所有成员大小
的公倍数。
结构体类型需要考虑到字节对齐的情况,不同的顺序会影响结构体的大小。
11) 关键字 volatile 有什么含意?并给出三个不同的例子。
【参考答案】一个定义为 volatile 的变量是说这变量可能会被意想不到地改
变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到
这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器
里的备份。下面是 volatile 变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
12) #include 和#include “filename.h” 有什么区别?
【标准答案】对于#include ,编译器从标准库路径开始搜
索 filename.h ;对于#include “filename.h” ,编译器从用户的工作路径开始搜
索 filename.h 。
13) const 有什么用途?(请至少说明两种)
【标准答案】:
(1)可以定义 const 常量,单独定义 const 变量没有明显的优势,完全
可以使用#define 命令代替。
(2)const 可以修饰函数的参数、返回值,甚至函数的定义体。被 const 修
饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
在 const int *p 中,忽略掉 int,被 const 直接修饰的是*p,*p 最终指向指针 p
指向的地址的内容,所以该内容不可变(至少不可以使用*p 进行修改),而变量
p 没有被 const 直接修饰,所以指正变量 p 最终指向的内容(也就是 p 本身的值)
是可变的。这样这一句可以等效于 int const *p。(这两种声明有没有其他的不同
之处,笔者暂时还不清楚)
在 int * const p 中,指针变量 p 本 const 直接修饰,所以 p 的内容(地址)是
不可变的,而 p 指向的地址的内容(即*p)没有被 const 直接修饰,所以 p 指向
的地址的内容是可变的,即*p 可以被再赋值。
14) static 有什么用途?(请至少说明两种)
【标准答案】
1. 限制变量的作用域(static 全局变量);
2. 设置变量的存储域(static 局部变量)。
一,static 全局变量
当一个进程的全局变量被声明为 static 之后,它的中文名叫静态全局变量。
静态全局变量和其他的全局变量的存储地点并没有区别,都是在.data 段(已初
始化)或者.bss 段(未初始化)内,但是它只在定义它的源文件内有效,其他源
文件无法访问它。所以,普通全局变量穿上 static 外衣后,它就变成了新娘,已
心有所属,只能被定义它的源文件(新郎)中的变量或函数访问。
二,static 局部变量
普通的局部变量在栈空间上分配,这个局部变量所在的函数被多次调用时,
每次调用这个局部变量在栈上的位置都不一定相同。局部变量也可以在堆上动态
分配,但是记得使用完这个堆空间后要释放之。static 局部变量中文名叫静态局
部变量。它与普通的局部变量比起来有如下几个区别:
1)位置:静态局部变量被编译器放在全局存储区.data(注意:不在.bss 段
内,原因见 3)),所以它虽然是局部的,但是在程序的整个生命周期中存在。
2)访问权限:静态局部变量只能被其作用域内的变量或函数访问。也就是
说虽然它会在程序的整个生命周期中存在,由于它是 static 的,它不能被其他的
函数和源文件访问。
3)值:静态局部变量如果没有被用户初始化,则会被编译器自动赋值为 0,
以后每次调用静态局部变量的时候都用上次调用后的值。这个比较好理解,每次
函数调用静态局部变量的时候都修改它然后离开,下次读的时候从全局存储区读
出的静态局部变量就是上次修改后的值。
三,static 函数
相信大家还记得 C++面向对象编程中的 private 函数,私有函数只有该类的
成员变量或成员函数可以访问。在 C 语言中,也有“private 函数”,它就是接下
来要说的 static 函数,完成面向对象编程中 private 函数的功能。
当你的程序中有很多个源文件的时候,你肯定会让某个源文件只提供一些外
界需要的接口,其他的函数可能是为了实现这些接口而编写,这些其他的函数你
可能并不希望被外界(非本源文件)所看到,这时候就可以用 static 修饰这些“其
他的函数”。
所以 static 函数的作用域是本源文件,把它想象为面向对象中的 private 函数
就可以了。
15) 如何引用一个已经定义过的全局变量?
【标准答案】可以用引用头文件的方式,也可以用 extern 关键字
如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那
个变量写错了,那么在编译期间会报错;
如果你用 extern 方式引用时,假定你犯了同样的错误,那么在编译期间不
会报错,而在连接期间报错。
16) A.c 和 B.c 两个 c 文件中使用了两个相同名字的 static 变量,编译的时候
会不会有问题?这两个 static 变量会保存到哪里(栈还是堆或者其他的)?
【标准答案】static 的全局变量,表明这个变量仅在本模块中有意义,不会
影响其他模块。
他们都放在静态数据区,但是编译器对他们的命名是不同的。
如果要使变量在其他模块也有意义的话,需要使用 extern 关键字。
17) 用两个栈实现一个队列的功能?要求给出算法和思路!
【参考答案】设 2 个栈为 A,B, 一开始均为空.
入队:
将新元素 push 入栈 A;
出队:
(1)判断栈 B 是否为空;
(2)如果不为空,则将栈 A 中所有元素依次 pop 出并 push 到栈 B;
(3)将栈 B 的栈顶元素 pop 出;
18) #define Max_CB 500
void LmiQueryCSmd(StructMSgCB * pmsg)
{
unsigned char ucCmdNum;
......
for(ucCmdNum=0;ucCmdNum
【标准答案】死循环
unsigned char //无符号字符型表示范围 0~255
char // 有符号字符型 表示范围-128~127
19) 一语句实现 x 是否为 2 的若干次幂的判断。
【参考答案】 void mai n()
{
i nt a;
scanf(“%d”,&a);
printf(“%c”,(a)&(a-1)?’n’:’y’); // 若是打印 y,否则 n
}
20) 下面的代码输出是什么,为什么?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b> 6)? puts("> 6") : puts("<= 6");
}
【参考答案】这个问题测试你是否懂得 C 语言中的整数自动转换原则,我
发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出
是“>6” 。原因是当表达式中存在有符号类型和无符号类型时所有的数都自动
转换为无符号类型。因此-20 变成了一个非常大的正整数,所以该表达式计算出
的结果大于 6 。这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是
丰常重要的。如果你答错了这个问题,你也就到了得不到这份工作的边缘。
1.2 宏定义
1) 头文件中的 ifndef/define/endif 干什么用?
【标准答案】防止该头文件被重复引用。
2) 以下关于 typedef 的叙述中错误的是: A
A. 用 typedef 可以增加新的类型
B. 用 typedef 可以定义各种类型名,但不能用来定义变量
C. 用 typedef 只是将已有的类型用新的标识符来代表
D. 使用 typedef 有利于程序的通用和移植
C 语言提供了 typedef 关键字,您可以使用它来为类型取一个新的名字。
下面的实例为单字节数字定义了一个术语 BYTE:typedef unsigned char BYTE;
在这个类型定义之后,标识符 BYTE 可作为类型 unsigned char 的缩写,
例如:BYTE b1, b2;
按照惯例,定义时会大写字母,以便提醒用户类型名称是一个象征性的缩写,
但您也可以使用小写字母,如下:typedef unsigned char byte;
您也可以使用 typedef 来为用户自定义的数据类型取一个新的名字。例如,
您可以对结构体使用 typedef 来定义一个新的数据类型名字,然后使用这个新的
数据类型来直接定义结构变量
#define 是 C 指令,用于为各种数据类型定义别名,与 typedef 类似,但
是它们有以下几点不同:
typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也
能为数值定义别名,比如您可以定义 1 为 ONE。
typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。
3) 以下关于宏替换的叙述不正确的是: D
A.宏替换只是字符替换 B.宏名无类型
C.宏替换不占用运行时间 D.宏替换不占用编译时间
4) 用宏定义写出 swap(x,y),即交换两数。
【标准答案】
#define swap(x, y) (x)=(x)+(y);(y)=(x)–(y);(x)=(x)–(y);
5) 带参宏与带参函数的区别(至少说出 5 点)?
【标准答案】
带参宏 带参函数
处理时间 编译时 运行时
参数类型 无 需定义
程序长度 变长 不变
占用存储空间 否 是
运行时间 不占运行时间 调用和返回时占
6) 已知一个数组 tabl e ,用一个宏定义,求出数据的元素个数。
【标准答案】
#define NTBL(table) (sizeof(table)/sizeof(table[0]))