C语言笔试题.docx
《C语言笔试题.docx》由会员分享,可在线阅读,更多相关《C语言笔试题.docx(35页珍藏版)》请在冰豆网上搜索。
C语言笔试题
一、请填写BOOL,float,指针变量与“零值”比较的if语句。
(10分)
请写出BOOL flag与“零值”比较的if语句。
(3分)
标准答案:
if(flag)
if(!
flag)
如下写法均属不良风格,不得分。
if(flag==TRUE)
if(flag==1)
if(flag==FALSE)
if(flag==0)
请写出float x与“零值”比较的if语句。
(4分)
标准答案示例:
constfloatEPSINON=0.00001;
if((x>=-EPSINON)&&(x<=EPSINON)
不可将浮点变量用“==”或“!
=”与数字比较,应该设法转化成“>=”或“<=”此类形式。
如下是错误的写法,不得分。
if(x==0.0)
if(x!
=0.0)
请写出char *p与“零值”比较的if语句。
(3分)
标准答案:
if(p==NULL)
if(p!
=NULL)
如下写法均属不良风格,不得分。
if(p==0)
if(p!
=0)
if(p)
if(!
)
二、以下为WindowsNT下的32位C++程序,请计算sizeof的值(10分)
char str[]=“Hello”;
char *p=str;
int n=10;
请计算
sizeof(str)= 6 (2分)
sizeof(p)= 4 (2分)
sizeof(n)= 4 (2分)
voidFunc(charstr[100])
{
请计算
sizeof(str)= 4 (2分)
}
void*p=malloc(100);
请计算
sizeof(p)= 4 (2分)
三、简答题(25分)
1、头文件中的ifndef/define/endif干什么用?
(5分)
答:
防止该头文件被重复引用。
2、#include 和 #include “filename.h”有什么区别?
(5分)
答:
对于#include ,编译器从标准库路径开始搜索filename.h
对于#include “filename.h”,编译器从用户的工作路径开始搜索filename.h
3、const有什么用途?
(请至少说明两种)(5分)
答:
(1)可以定义const常量
(2)const可以修饰函数的参数、返回值,甚至函数的定义体。
被const修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。
4、在C++程序中调用被C编译器编译后的函数,为什么要加extern“C”?
(5分)
答:
C++语言支持函数重载,C语言不支持函数重载。
函数被C++编译后在库中的名字与C语言的不同。
假设某个函数的原型为:
voidfoo(intx,inty);
该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。
C++提供了C连接交换指定符号extern“C”来解决名字匹配问题。
5、请简述以下两个for循环的优缺点(5分)
for(i=0;ii++)
{
if(condition)
DoSomething();
else
DoOtherthing();
}
if(condition)
{
for(i=0;ii++)
DoSomething();
}
else
{
for(i=0;ii++)
DoOtherthing();
}
优点:
程序简洁
缺点:
多执行了N-1次逻辑判断,并且打断了循环“流水线”作业,使得编译器不能对循环进行优化处理,降低了效率。
优点:
循环的效率高
缺点:
程序不简洁
四、有关内存的思考题(每小题5分,共20分)
voidGetMemory(char*p)
{
p=(char*)malloc(100);
}
voidTest(void)
{
char*str=NULL;
GetMemory(str);
strcpy(str,"helloworld");
printf(str);
}
请问运行Test函数会有什么样的结果?
答:
试题传入GetMemory(char*p)函数的形参为字符串指针,在函数内部修改形参并不能真正的改变传入形参的值,执行完
char*str=NULL;
GetMemory(str);
后的str仍然为NULL;
char*GetMemory(void)
{
charp[]="helloworld";
returnp;
}
voidTest(void)
{
char*str=NULL;
str=GetMemory();
printf(str);
}
请问运行Test函数会有什么样的结果?
答:
可能是乱码。
charp[]="helloworld";
returnp;
的p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。
这是许多程序员常犯的错误,其根源在于不理解变量的生存期。
voidGetMemory2(char**p,intnum)
{
*p=(char*)malloc(num);
}
voidTest(void)
{
char*str=NULL;
GetMemory(&str,100);
strcpy(str,"hello");
printf(str);
}
请问运行Test函数会有什么样的结果?
答:
(1)能够输出hello
(2)Test函数中也未对malloc的内存进行释放。
(3)GetMemory避免了试题1的问题,传入GetMemory的参数为字符串指针的指针,但是在GetMemory中执行申请内存及赋值语句
*p=(char*)malloc(num);
后未判断内存是否申请成功,应加上:
if(*p==NULL)
{
...//进行申请内存失败处理
}
voidTest(void)
{
char*str=(char*)malloc(100);
strcpy(str,“hello”);
free(str);
if(str!
=NULL)
{
strcpy(str,“world”);
printf(str);
}
}
请问运行Test函数会有什么样的结果?
答:
执行
char*str=(char*)malloc(100);
后未进行内存是否申请成功的判断;另外,在free(str)后未置str为空,导致可能变成一个“野”指针,应加上:
str=NULL;
五、编写strcpy函数(10分)
已知strcpy函数的原型是
char*strcpy(char*strDest,constchar*strSrc);
其中strDest是目的字符串,strSrc是源字符串。
(1)不调用C++/C的字符串库函数,请编写函数strcpy
char*strcpy(char*strDest,constchar*strSrc);
{
assert((strDest!
=NULL)&&(strSrc!
=NULL)); //2分
char*address=strDest; //2分
while((*strDest++=*strSrc++)!
=‘\0’) //2分
NULL;
returnaddress; //2分
}
(2)strcpy能把strSrc的内容复制到strDest,为什么还要char*类型的返回值?
答:
为了实现链式表达式。
//2分
例如 intlength=strlen(strcpy(strDest,“helloworld”));
六、编写类String的构造函数、析构函数和赋值函数(25分)
已知类String的原型为:
classString
{
public:
String(constchar*str=NULL);//普通构造函数
String(constString&other); //拷贝构造函数
~String(void); //析构函数
String&operate=(constString&other); //赋值函数
private:
char *m_data; //用于保存字符串
};
请编写String的上述4个函数。
标准答案:
//String的析构函数
String:
:
~String(void) //3分
{
delete[]m_data;
//由于m_data是内部数据类型,也可以写成deletem_data;
}
//String的普通构造函数
String:
:
String(constchar*str) //6分
{
if(str==NULL)
{
m_data=newchar[1]; //若能加NULL判断则更好
*m_data=‘\0’;
}
else
{
intlength=strlen(str);
m_data=newchar[length+1]; //若能加NULL判断则更好
strcpy(m_data,str);
}
}
//拷贝构造函数
String:
:
String(constString&other) //3分
{
intlength=strlen(other.m_data);
m_data=newchar[length+1]; //若能加NULL判断则更好
strcpy(m_data,other.m_data);
}
//赋值函数
String&String:
:
operate=(constString&other) //13分
{
//
(1)检查自赋值 //4分
if(this==&other)
return*this;
//
(2)释放原有的内存资源 //3分
delete[]m_data;
//(3)分配新的内存资源,并复制内容//3分
intlength=strlen(other.m_data);
m_data=newchar[length+1]; //若能加NULL判断则更好
strcpy(m_data,other.m_data);
//(4)返回本对象的引用 //3分
return*this;
}
华为笔试
2006-2-28星期二(Tuesday)晴
1、局部变量能否和全局变量重名?
答:
局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。
对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内
2、如何引用一个已经定义过的全局变量?
答:
可以用引用头文件的方式,也可以用extern关键字,如果用引用头文件方式来引用某个在头文件中声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,如果你用extern方式引用时,假定你犯了同样的错误,那么在编译期间不会报错,而在连接期间报错。
(不要问我什么是编译期间,什么是连接期间,请自己查资料)
3、全局变量定义在可被多个.C文件包含的头文件中可不可以?
为什么?
答:
可以,但要加static
4、语句for(;1;)有什么问题?
它是什么意思?
答:
死循环,同while
(1),这种写法并不规范,可读性差,一般不用
5、do……while和while……do有什么区别?
答:
前一个循环一遍再判断,后一个判断以后再循环
6、请写出下列代码的输出内容
#include
main()
{
inta,b,c,d;
a=10;
b=a++;
c=++a;
d=10*a++;
printf("b,c,d:
%d,%d,%d",b,c,d);
return0;
}
答:
10,12,120
7.static函数与普通函数有什么区别?
只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。
对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件。
8.static全局变量与普通的全局变量有什么区别?
全局变量(外部变量)的说明之前再冠以static就构成了静态的全局变量。
全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。
这两者在存储方式上并无不同。
这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。
而静态全局变量则限制了其作用域,即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。
由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
从以上分析可以看出,把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。
把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。
9.程序的局部变量存在于(栈)中,全局变量存在于(静态区)中,动态申请数据存在于(堆)中。
10.设有以下说明和定义:
typedefunion{longi;intk[5];charc;}DATE;
structdata{intcat;DATEcow;doubledog;}too;
DATEmax;
则语句printf("%d",sizeof(structdate)+sizeof(max));的执行结果是:
___52____
11.队列和栈有什么区别?
队列先进先出,栈后进先出
12.写出下列代码的输出内容
#include
intinc(inta)
{
return(++a);
}
intmulti(int*a,int*b,int*c)
{
return(*c=*a**b);
}
typedefint(FUNC1)(intin);
typedefint(FUNC2)(int*,int*,int*);
voidshow(FUNC2fun,intarg1,int*arg2)
{
INCp=&inc;
inttemp=p(arg1);
fun(&temp,&arg1,arg2);
printf("%d\n",*arg2);
}
main()
{
inta;
show(multi,10,&a);
return0;
}
翻译一下
==================================
#include
usingnamespacestd;
//返回a+1
intinc(inta){
returna+1;
}
//out=a*b
intmulti(int&a,int&b,int&out){
returnout=a*b;
}
//定义两种函数,FUNC1对应inc,FUNC2对应multi
typedefint(FUNC1)(intin);
typedefint(FUNC2)(int&,int&,int&);
//诡异的函数,这是模糊C大赛么...
voidshow(FUNC2*func,intnum,int&out){
FUNC1*pInc=inc;//原文这句写错了...orz...INC根本没定义
intnumAdd1=pInc(num);
//等价于numAdd1=inc(num);
//结果num仍然是10,numAdd1=11
//调用func函数,可以看到,main中传给func的是multi.
//所以调用的是multi(11,10,out),out=110
func(numAdd1,num,out);
cout<}
intmain(){
inta;
show(multi,10,a);
return0;
}
==================================
13.请找出下面代码中的所以错误
说明:
以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”
==================================
main(){
char*src="hello,world";
char*dest=NULL;
intlen=strlen(src);
dest=(char*)malloc(len);//!
1少分配了一字节.strlen计数不包括\0
char*d=dest;
char*s=src[len];//!
2两个错误.应该为&src[len-1]
while(len--!
=0)
d++=s--;//!
3*d++=*s--;
//!
4尾部要\0,应加上*d=0;
printf("%s",dest);
return0;
}
==================================
修正后的答案:
==================================
intmain(){
char*src="hello,world";
intlen=strlen(src);
char*dest=(char*)malloc(len+1);.
char*d=dest;
char*s=&src[len-1];
while(len--!
=0)
*d++=*s--;
*d=0;
printf("%s",dest);
return0;
}
==================================
#postedby孜孜不倦心@2006-02-2822:
24评论
(1)
什么是IP协议?
2006-2-27星期一(Monday)小雪
TCP/IP(TransmissionControlProtocol/InternetProtocol的简写,中文译名为传输控制协议/互联网络协议)协