现在的位置: 首页 > 综合 > 正文

面试题总结 – C 语言 – 关键字(keywords)

2013年09月11日 ⁄ 综合 ⁄ 共 3030字 ⁄ 字号 评论关闭

1. 关键字Static的作用是什么?

answer: 这个简单的问题很少有人能回答完全,在C语言中,关键字static 有三个明显的作用:

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

2, 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内的所有函数访问,但不能被模块外地其他函数访问,因为他是一个本地的全局变量。

3,在模块内,一个被声明为静态的函数只可被这一模块内的其他函数调用,那即是,这个函数被定义在声明它的模块的本地范围内使用。

2. 关键字const是什么含义?

answer: 我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded SystemsProgramming)的每一位读者应该非常熟悉const能做什么和不能做什么.
如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。)如果应试者能正确回答这个问题,我将问他一个附加的问题:下面的声明都是什么意思?

const int a;
int const a;
const int *a;
int * const a;
int const * a const;

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

3. 关键字volatile有什么含意并给出三个不同的例子。

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。
假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。
1). 一个参数既可以是const还可以是volatile吗?解释为什么。
2). 一个指针可以是volatile 吗?解释为什么。
3). 下面的函数有什么错误:
int square(volatile int *ptr)
{
return *ptr * *ptr;
}
下面是答案:
1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。
2). 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。
3). 这段代**的有个恶作剧。这段代**的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代**:
int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}
由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代**可能返不是你所期望的平方值!正确的代**如下:
long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}

位**作(Bit manipulation)

3.

#include<setjmp.h>
static jmp_buf  buf;

main()   
{
  volatile  int b;
  b =3;

  if(setjmp(buf)!=0) 
  {
    printf("%d ", b); 
    exit(0);
  }
  b=5;
  longjmp(buf , 1);
}

请问,这段程序的输出是
(a) 3
(b) 5
(c) 0
(d) 以上均不是

answer:

volatile字面意思是易于挥发的。这个关键字来描述一个变量时,意味着 给该变量赋值(写入)之后,马上再读取,写入的值与读取的值可能不一样,所以说它"容易挥发"的。
这是因为这个变量可能一个寄存器,直接与外部设备相连,你写入之后,该寄存器也有可能被外部设备的写操作所改变;或者,该变量被一个中断程序,或另一个进程
改变了.
volatile 不会被编译器优化影响,在longjump 后,它的值 是后面假定的变量值,b最后的值是5,所以5被打印出来.

setjmp : 设置非局部跳转 /* setjmp.h*/

Stores context information such as register values so that the lomgjmp functioncan return control to the statement following the one calling setjmp.Returns 0when it is initially called.

Lonjjmp: 执行一个非局部跳转 /* setjmp.h*/

Transfers control to the statement where the call to setjmp (which initializedbuf) was made. Execution continues at this point as if longjmp cannot returnthe value 0.A nonvolatile automatic variable might be changed by a call tolongjmp.When you use setjmp and
longjmp, the only automatic variablesguaranteed to remain valid are those declared volatile.

Note: Test program without volatile qualifier (result may very)

更详细介绍,请参阅 C语言的setjmp和longjmp

抱歉!评论已关闭.