c 语言常见笔试题.docx

上传人:b****8 文档编号:23986303 上传时间:2023-05-23 格式:DOCX 页数:14 大小:21.09KB
下载 相关 举报
c 语言常见笔试题.docx_第1页
第1页 / 共14页
c 语言常见笔试题.docx_第2页
第2页 / 共14页
c 语言常见笔试题.docx_第3页
第3页 / 共14页
c 语言常见笔试题.docx_第4页
第4页 / 共14页
c 语言常见笔试题.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

c 语言常见笔试题.docx

《c 语言常见笔试题.docx》由会员分享,可在线阅读,更多相关《c 语言常见笔试题.docx(14页珍藏版)》请在冰豆网上搜索。

c 语言常见笔试题.docx

c语言常见笔试题

关键字static的作用是什么?

这个简单的问题很少有人能回答完全。

在C语言中,关键字static有三个明显的作用:

1).在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。

2).在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。

它是一个本地的全局变量。

3).在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。

那就是,这个函数被限制在声明它的模块的本地范围内使用。

关键字const是什么含意?

我只要一听到被面试者说:

“const意味着常数”,我就知道我正在和一个业余者打交道。

去年DanSaks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:

EmbeddedSystemsProgramming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。

尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。

(如果你想知道更详细的答案,仔细读一下Saks的文章吧。

)如果应试者能正确回答这个问题,我将问他一个附加的问题:

下面的声明都是什么意思?

constinta;

intconsta;

constint*a;

int*consta;

intconst*aconst;

前两个的作用是一样,a是一个常整型数。

第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。

第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。

最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。

顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?

我也如下的几下理由:

1).关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。

如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。

(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。

2).通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。

3).合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。

简而言之,这样可以减少bug的出现。

C语言同意一些令人震惊的结构,下面的结构是合法的吗,如果是它做些什么?

inta=5,b=7,c;

c=a+++b;

这个问题将做为这个测验的一个愉快的结尾。

不管你相不相信,上面的例子是完全合乎语法的。

问题是编译器如何处理它?

水平不高的编译作者实际上会争论这个问题,根据最处理原则,编译器应当能处理尽可能所有合法的用法。

因此,上面的代码被处理成:

c=a+++b;

因此,这段代码持行后a=6,b=7,c=12。

如果你知道答案,或猜出正确答案,做得好。

如果你不知道答案,我也不把这个当作问题。

我发现这个问题的最大好处是:

这是一个关于代码编写风格,代码的可读性,代码的可修改性的好的话题

Typedef在C语言中频繁用以声明一个已经存在的数据类型的同义字。

也可以用预处理器做类似的事。

例如,思考一下下面的例子:

#definedPSstructs*

typedefstructs*tPS;

以上两种情况的意图都是要定义dPS和tPS作为一个指向结构s指针。

哪种方法更好呢?

(如果有的话)为什么?

这是一个非常微妙的问题,任何人答对这个问题(正当的原因)是应当被恭喜的。

答案是:

typedef更好。

思考下面的例子:

dPSp1,p2;

tPSp3,p4;

第一个扩展为

structs*p1,p2;

上面的代码定义p1为一个指向结构的指,p2为一个实际的结构,这也许不是你想要的。

第二个例子正确地定义了p3和p4两个指针。

尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。

那么嵌入式系统中,动态分配内存可能发生的问题是什么?

这里,我期望应试者能提到内存碎片,碎片收集的问题,变量的持行时间等等。

这个主题已经在ESP杂志中被广泛地讨论过了(主要是P.J.Plauger,他的解释远远超过我这里能提到的任何解释),所有回过头看一下这些杂志吧!

让应试者进入一种虚假的安全感觉后,我拿出这么一个小节目:

下面的代码片段的输出是什么,为什么?

char*ptr;

if((ptr=(char*)malloc(0))==NULL)

puts("Gotanullpointer");

else

puts("Gotavalidpointer");

这是一个有趣的问题。

最近在我的一个同事不经意把0值传给了函数malloc,得到了一个合法的指针之后,我才想到这个问题。

这就是上面的代码,该代码的输出是“Gotavalidpointer”。

我用这个来开始讨论这样的一问题,看看被面试者是否想到库例程这样做是正确。

得到正确的答案固然重要,但解决问题的方法和你做决定的基本原理更重要些。

下面的代码输出是什么,为什么?

voidfoo(void)

{

unsignedinta=6;

intb=-20;

(a+b>6)?

puts(">6"):

puts("<=6");

}

这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。

不管如何,这无符号整型问题的答案是输出是“>6”。

原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。

因此-20变成了一个非常大的正整数,所以该表达式计算出的结果大于6。

这一点对于应当频繁用到无符号数据类型的嵌入式系统来说是丰常重要的。

如果你答错了这个问题,你也就到了得不到这份工作的边缘。

用变量a给出下面的定义

a)一个整型数(Aninteger)

b)一个指向整型数的指针(Apointertoaninteger)

c)一个指向指针的的指针,它指向的指针是指向一个整型数(Apointertoapointertoaninteger)

d)一个有10个整型数的数组(Anarrayof10integers)

e)一个有10个指针的数组,该指针是指向一个整型数的(Anarrayof10pointerstointegers)

f)一个指向有10个整型数数组的指针(Apointertoanarrayof10integers)

g)一个指向函数的指针,该函数有一个整型参数并返回一个整型数(Apointertoafunctionthattakesanintegerasanargumentandreturnsaninteger)

h)一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(Anarrayoftenpointerstofunctionsthattakeaninteger

argumentandreturnaninteger)

答案是:

a)inta;//Aninteger

b)int*a;//Apointertoaninteger

c)int**a;//Apointertoapointertoaninteger

d)inta[10];//Anarrayof10integers

e)int*a[10];//Anarrayof10pointerstointegers

f)int(*a)[10];//Apointertoanarrayof10integers

g)int(*a)(int);//Apointertoafunctionathattakesanintegerargumentandreturnsaninteger

h)int(*a[10])(int);//Anarrayof10pointerstofunctionsthattakeanintegerargumentandreturnaninteger

嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?

这个问题用几个解决方案。

我首选的方案是:

while

(1)

{

}

一些程序员更喜欢如下方案:

for(;;)

{

}

这个实现方式让我为难,因为这个语法没有确切表达到底怎么回事。

如果一个应试者给出这个作为方案,我将用这个作为一个机会去探究他们这样做的

基本原理。

如果他们的基本答案是:

“我被教着这样做,但从没有想到过为什么。

”这会给我留下一个坏印象。

第三个方案是用goto

Loop:

...

gotoLoop;

应试者如给出上面的方案,这说明或者他是一个汇编语言程序员(这也许是好事)或者他是一个想进入新领域的BASIC/FORTRAN程序员。

分析下面的程序:

voidGetMemory(char**p,intnum)

{

*p=(char*)malloc(num);

}

intmain()

{

char*str=NULL;

GetMemory(&str,100);

strcpy(str,"hello");

free(str);

if(str!

=NULL)

{

strcpy(str,"world");

}

printf("\nstris%s",str);

getchar();

}

问输出结果是什么?

答案:

输出strisworld。

free只是释放的str指向的内存空间,它本身的值还是存在的.

所以free之后,有一个好的习惯就是将str=NULL.

此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,

尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。

这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。

当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存前面一点),并将可用内存的地址返回。

但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的,只不过。

楼上都说过了,最好别这么干。

2。

运行的结果为什么等于15

#include"stdio.h"

#include"string.h"

voidmain()

{

charaa[10];

printf("%d",strlen(aa));

}

答案:

sizeof()和初不初始化,没有关系;strlen()和初始化有关。

3。

给定结构structA

{

chart:

4;

chark:

4;

unsignedshorti:

8;

unsignedlongm;

};问sizeof(A)=?

答案:

给定结构

structA

{

chart:

4;//4位

chark:

4;//4位

unsignedshorti:

8;//8位这里要偏移2字节保证4字节对齐

unsignedlongm;//4个字节

};//共8字节

4。

分析一下

#include

#include

#include

#include

#include

#include

typedefstructAA

{

intb1:

5;

intb2:

2;

}AA;

voidmain()

{

AAaa;

charcc[100];

strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");

memcpy(&aa,cc,sizeof(AA));

cout<

cout<

}

答案:

-16和1

首先sizeof(AA)的大小为4,b1和b2分别占5bit和2bit.

经过strcpy和memcpy后,aa的4个字节所存放的值是:

0,1,2,3的ASC码,即00110000,00110001,00110010,00110011

所以,最后一步:

显示的是这4个字节的前5位,和之后的2位

分别为:

10000,和01

因为int是有正负之分  所以是-16和1

5。

求函数返回值,输入x=9999;

intfunc(x)

{

intcountx=0;

while(x)

{

countx++;

x=x&(x-1);

}

returncountx;

}

结果呢?

答案:

知道了这是统计9999的二进制数值中有多少个1的函数,且有

9999=9×1024+512+256+15

9×1024中含有1的个数为2;

512中含有1的个数为1;

256中含有1的个数为1;

15中含有1的个数为4;

故共有1的个数为8,结果为8。

1000-1=0111,正好是原数取反。

这就是原理。

用这种方法来求1的个数是很效率很高的。

不必去一个一个地移位。

循环次数最少。

6。

inta,b,c请写函数实现C=a+b,不可以改变数据类型,如将c改为longint,关键是如何处理溢出问题

答案:

booladd(inta,intb,int*c)

{

*c=a+b;

return(a>0&&b>0&&(*ca||*c>b)));

}

7。

分析:

structbit

{inta:

3;

intb:

2;

intc:

3;

};

intmain()

{

bits;

char*c=(char*)&s;

cout<

*c=0x99;

cout<

inta=-1;

printf("%x",a);

return0;

}

输出为什么是?

答案:

4

1

-1

-4

ffffffff

因为0x99在内存中表示为10011001,a=001,b=11,c=100(在vc环境中,一般是由右到左进行分配的)

当c为有符合数时,c=100,最高1为表示c为负数,负数在计算机用补码表示,所以c=-4;同理

b=-1;

当c为有符合数时,c=100,即c=4,同理b=3

8。

改错:

#include

intmain(void){

int**p;

intarr[100];

p=&arr;

return0;

}

答案:

搞错了,是指针类型不同,

int**p;//二级指针

&arr;//得到的是指向第一维为100的数组的指针

应该这样写#include

intmain(void){

int**p,*q;

intarr[100];

q=arr;

p=&q;

return0;

9。

下面这个程序执行后会有什么错误或者效果:

#defineMAX255

intmain()

{

unsignedcharA[MAX],i;//i被定义为unsignedchar

for(i=0;i<=MAX;i++)

A[i]=i;

}

答案:

死循环加数组越界访问(C/C++不进行数组越界检查)

MAX=255

数组A的下标范围为:

0..MAX-1,这是其一..

其二.当i循环到255时,循环内执行:

A[255]=255;

这句本身没有问题..但是返回for(i=0;i<=MAX;i++)语句时,

由于unsignedchar的取值范围在(0..255),i++以后i又为0了..无限循环下去.

11。

structname1{

charstr;

shortx;

intnum;

}

structname2{

charstr;

intnum;

shortx;

}

sizeof(structname1)=?

sizeof(structname2)=?

答案:

sizeof(structname1)=8,sizeof(structname2)=12

在第二个结构中,为保证num按四个字节对齐,char后必须留出3字节的空间;同时为保证整个结构的自然对齐(这里是4字节对齐),在x后还要补齐2个字节,这样就是12字节。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1