1、如何判断一段程序是由C编译程序还是由C++编译程序编译的?
答案:C++编译时定义了_cplusplus,C编译时定义了_STDC_。
------------------------------------------------------
2、在C++程序中调用C编译器编译后的函数,为什么要加extern “C” ?
答案:C++语言支持函数重载,C语言不支持函数重载。函数被C++编译后在库中的名字与C语言的不同。如假设某个函数原型为:void foo(int x,int y),则该函数被C编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字。因此C++提供了C连接交换指定符号extern “C”来解决名字匹配问题。
------------------------------------------------------
3、main主函数执行完毕后,是否可能会再执行一段代码?给出说明。(美国某著名网络开发公司2005年面试题)
答案:如果需要加入一段在main函数退出后执行的代码,可以使用atexit()函数注册一个函数,代码如下:
#include <stdio.h>
#include <stdlib.h>
int atexit(void (*function)(void));
void fn1(void), fn2(void), fn3(void), fn4(void);
int main()
{
atexit(fn1);
atexit(fn2);
atexit(fn3);
atexit(fn4);
printf("This is executed first./n");
return 0;
}
void fn1()
{
printf("next./n");
}
void fn2()
{
printf("executed ");
}
void fn3()
{
printf("is ");
}
void fn4()
{
printf("This ");
}
------------------------------------------------------
上述程序运行后的结果为:
显然出现上述结果的关键是函数atexit(),下面介绍下atexit()函数:
atexit函数的功能是注册终止函数,函数原型为int atexit(atexit_t func);
需要注意的是atexit()注册的函数类型应为不接受任何参数的void函数,exit调用这些注册函数的顺序与它们登记时候的顺序相反,即atexit是注册后进先出的函数,和函数入栈出栈是一样的。实际上这个过程也不完全算main执行完毕后还能执行代码,因为exit的过程仍处于main结束的过程中。
上述程序中atexit注册了四个函数,理解为入栈的顺序为fn1()-> fn2()-> fn3()-> fn4(),因此出栈的顺序正好相反,而什么时候出栈呢?就是在调用函数结束时,准确的说应该是函数调用的最后的操作就是出栈过程。main()同样也是一个函数,在结束时,按出栈的顺序调用四个函数,即为fn4()-> fn3()-> fn2()-> fn1();注册这个函数的目的就是为了在函数退出时调用的,即使是main()函数也是这样的。可以在这些函数中加入一些清理工作,比如内存释放等等。
其实进程的终止方式有8种,分别是(1)从main返回;(2)调用exit;(3)调用_exit或_Exit;(4)最后一个线程从启动例程返回;(5)最后一个线程调用pthread_exit;(6)调用abort;(7)接到一个信号并终止;(8)最后一个线程对取消请求作出响应。其中前5种是正常终止,后3种是异常终止。
参考资料
[1]《程序员面试宝典》
[2] http://baike.baidu.com/view/653930.htm
[3] http://topic.csdn.net/u/20090821/08/d7f9c585-4d92-4f74-826c-0197996b7e17.html