C、C++工程师面试题

http://blog.csdn.net/rl529014/article/details/51671270

题目:什么是预编译?何时需要预编译?

    答:
什么是预编译:
  • 预编译又称为预处理 , 是做些代码文本的替换工作。
  • 处理以# 开头的指令 , 比如拷贝 #include 包含的文件代码,#define 宏定义的替换 , 条件编译等,就是为编译做的预备工作的阶段。

  • 主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。

  • C 编译系统在对程序进行通常的编译之前,首先进行预处理。
 c 提供的预处理功能主要有以下三种:

 1 )宏定义 

 2 )文件包含 

 3 )条件编译

何时需要预编译:

  • 总是使用不经常改动的大型代码体。
  • 程序由多个模块组成,所有模块都使用一组标准的包含文件和相同的编译选项。在这种情况下,可以将所有包含文件预编译为一个“预编译头”

题目:

要求:将数a、b的值进行交换,并且不使用任何中间变量。


程序如下:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>  
  2.   
  3. void swapValue1(int &a, int &b) //使用中间变量交换数据  
  4. {  
  5.     int temp = a;  
  6.     a = b;  
  7.     b = temp;  
  8. }  
  9.   
  10. void swapValue2(int &a, int &b)//使用加减运算完成数据交换  
  11. {  
  12.     a = a + b;  
  13.     b = a - b;  
  14.     a = a - b;    
  15. }  
  16.   
  17. void swapValue3(int &a, int &b) //使用位运算交换数据  
  18. {  
  19.     a^=b;  
  20.     b^=a;  
  21.     a^=b;  
  22. }  
  23. int main()  
  24. {  
  25.     int a1 = 1, b1 = 2;  
  26.     int a2 = 3, b2 = 4;  
  27.     int a3 = 5, b3 = 6;  
  28.       
  29.     swapValue1(a1, b1);  
  30.     swapValue2(a2, b2);  
  31.     swapValue3(a3, b3);  
  32.       
  33.     printf("a= %d  b= %d\n",a1, b1);  
  34.     printf("a= %d  b= %d\n",a2, b2);  
  35.     printf("a= %d  b= %d\n",a3, b3);  
  36.       
  37.     return 0;  
  38. }   


运行结果:



解析:

第一种:

使用中间变量来达到交换数据的目的,这是最大众的方法,当然了不满足本题的要求。


第二种:

使用简单的加减操作来达到交换a、b值得目的。

缺点:a+b和a-b时,可能会到导致数据溢出。


第三种:

采用位运算的方法,按位异或运算。(建议采用这种方式)

异或运算:相同的二进制位异或运算为0,不相同的二进制位异或运算为1。


初次从面试宝典中看到这个问题,我那也是一脸的懵逼啊。老师一直告诉我们,main是函数的入口地址,执行完成后,就返回操作系统了。殊不知还有这么多没了解过的知识。

题目:

main()函数执行完后,还会调用执行其他的语句吗?

       我们通常认为C语言的起始函数是main()函数,实质上一个程序的启动函数并不一定是main()函数,这个可以采用链接器来设置,但是gcc中默认main()就是C语言的入口函数,在main函数启动之前,内核会调用一个特殊的启动例程,这个启动例程从内核中取得命令行参数值和环境变量值,为调用main()函数做好准备。

      因此对应程序而言main()函数并不是起始,但是对应C 语言而言,main()函数就是入口地址。

      按照ISO C的规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用,通常这32个函数被称为终止处理程序,并调用atexit()函数来登记这些函数。 (函数的调用顺序与注册的顺序是相反的,通过下面的实例可以看出来)     

举例

代码如下:

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>  
  2. #include<stdlib.h>  
  3. void fun1(void)  
  4. {  
  5.     printf("fun1\n");  
  6. }  
  7.   
  8. void fun2(void)  
  9. {  
  10.     printf("fun2\n");     
  11. }  
  12.   
  13. void fun3(void)  
  14. {  
  15.     printf("fun3\n");  
  16. }  
  17. int main()  
  18. {  
  19.     atexit(fun1);  
  20.     atexit(fun2);  
  21.     atexit(fun3);  
  22.       
  23.     printf("main exit\n");  
  24.       
  25.     return 0;  
  26. }   

运行结果:



函数说明:

头文件:#include <stdlib.h>

定义函数:int atexit (void (*function) (void));

atexit()用来设置一个程序正常结束前调用的函数. 当程序通过调用exit()或从main()中返回时, 参数function 所指定的函数会先被调用, 然后才真正由exit()结束程序。




问题:

请指出下面这个程序在C和C++中的输出分别是什么?

[cpp]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>  
  2.   
  3. int value = 0;  
  4.   
  5. void printValue()  
  6. {  
  7.     printf("value = %d\n",value);  
  8. };  
  9.   
  10. int main()  
  11. {  
  12.     int value = 0;  
  13.     value = 1;  
  14.         printf("value = %d\n",value);  
  15.     ::value = 2;  
  16.     printValue();  
  17.       
  18.     return 0;  
  19. }   

解析:

将程序的后缀名保存为.c

那么程序将在编译阶段出错。提示有语法错误,因为在C中,并没有域操作符。

编译器的提示为:



将后缀名保存为.cpp

此时程序将成功运行。第一个value是局部变量value的值,第二个value是修改过后的全局变量value的值。

运行结果为:



常量指针:指向常量的指针。

  • 指针本身可以改变,可以再次指向另外的对象。
  • 不能通过指针修改其所指向的对象的值。
  • 对象本身的值可以直接修改。


指针常量:指针类型的常量。

  • 指针本身的值不能改变,即不能再指向另外的对象。
  • 可以修改指针所指对象的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值