您的位置:首页 > 职场人生

程序员面试笔试宝典——读书笔记3、预处理、结构体与类、位操作

2015-08-27 19:09 453 查看
五、预处理

预处理也成为预编译,它为编译做预备工作,主要进行代码文本的替换工作,用于处理#开头的指令,其中预处理器产生编译器的输出。

1、C/C++ 头文件中的ifndef /define /endif 的作用有哪些?

如果一个项目中存在两个C文件,而这两个C文件都include了同一个头文件,当编译时,这两个C文件要一同编译成一个可运行文件,可能会产生大量的声明冲突。而解决的办法是把头文件的内容都放在#ifndef 和#endif 中。



2、#include <filename.h> 和 #include "filename.h"有什么区别

对于#include <filename.h>,编译器先从标准库路径开始搜索filename.h, 使得系统文件调用较快。而对于 #include "filename.h",编译器先从用户的工作路径开始搜索,然后去寻找系统路径,使得自定义文件较快。

3、#define 有哪些缺陷

由于宏定义在预处理阶段进行,主要做的是字符替换工作,存在的缺陷:

a、它无法进行类型检查

b、由于优先级不同,使用宏定义时,可能会存在副作用。如#define ADD(a,b)  a+b 就会存在问题,需要加括号。

c、无法单步调试。

d、会导致代码膨胀

e、在C++中,使用宏无法操作类的私有数据成员。



4、如何使用define 声明一个常数,用以表明 1 年有多少秒 (忽略闰年问题)

#define  SECOND_PER_YEAR   (60*60*24*365)UL
(考虑到溢出,所以使用长整型)



5、含参数的宏与函数有什么区别

含参数的宏有时完成的是函数实现的功能,但是并非所有的函数都可以被含参数的宏所替代。

两者的特点:

a、函数调用时,首先求出实参表达式的值,然后代入形参。而使用带参的宏只是进行简单的字符替换。

b、函数调用是在程序运行时处理的,它需要分配临时的内存单元;而宏展开则是在编译时进行的,在展开时并不分配内存单元,也不进行值的传递处理,也没有“返回值”的概念。

c、对函数中的实参和形参都要定义类型。两者的类型要求一致,如果不一致,应进行类型转换;而宏不存在类型问题,宏名无类型,它的参数也无类型,只是一个符号代表,展开时代入指定的字符即可。宏定义时,字符串可以是任何类型的数据。

d、调用函数只可得到一个返回值,而用宏可以设法得到几个结果。

e、使用宏次数多时,宏展开后源程序会变得很长,因为每展开一次都使得程序内容增长,而函数调用不使源程序变长。

f、宏替换不占用运行时间,而函数调用则占运行时间。

g、参数每次用于宏定义时,它们都将重新求值,由于多次求值,具有副作用的参数可能会产生不可预料的结果。而函数调用则不会

一般来说,用宏来代替简短的表达式比较合适。

6、宏定义平方运算#define    SQR(X)   X*X  是否正确

不正确,会造成错误。



7、不能使用大于、小于、if 语句,如何定义一个宏来比较a、b 的大小

#define MIN(A,B)  ((A) <= (B) ? (A): (B))



8、如何判断一个变量是有符号还是无符号数

有三种方法:

a、采用取反操作

b、无符号数和有符号数相减的结果为无符号数。

c、通过改变符号位判断。



9、#define TRACE(S)   (printf(“%S\n”,#S),S) 是什么意思

#进行宏字符串连接,在宏中把参数解释为字符串,不可以在语句中直接使用。



10、不使用sizeof ,如何求int 占用的字节数

采用地址值相减。



11、如何使用宏求结构体的内存偏移地址(不会)

#define OffSet(type, field) ((size_t)&((type *)0-> field))[具体的解释百度]



12、如何用sizeof 判断数组中有多少个元素

用整个数组的sizeof 去除以一个元素的sizeof 即可。



13、枚举和define 有什么区别

区别很小。

在C语言中,枚举为整型,枚举常量为 int  型。

具体区别:

a、枚举常量是实体中的一种,而宏定义不是实体

b、枚举常量属于常量,但宏定义不是常量。

c、枚举常量具有类型,但宏定义没有类型,枚举变量具有普通变量相同的性质,但宏没有。

d、#define 宏常量是在预编译阶段进行简单的值替换,枚举常量则是在编译的时候确定其值。

e、一般在编译器里可以调试枚举变量,但宏常量不行。

f、枚举可以一次定义大量相关的常量,而#define 宏一次只能定义一个。



14、typedef 的define 有什么区别

区别:

a、原理不同。#define 是预处理指令,不做正确性检查;typedef 是关键字,有类型检查功能。

b、功能不同。typedef 用来定义类型的别名,是类型易于记忆。而#define 不只是取别名,还可以定义常量、变量、编译开关等。

c、作用域不同。#define 没有作用域限制;而typedef 有自己的作用域。

d、对指针的操作不同。作用不同。

15、C++ 中宏定义与内联函数有什么区别

宏代码本身不是函数,但使用起来却像函数,预处理器用复制宏代码的方式代替函数调用,省去了参数压栈、生成汇编语言的CALL调用,返回参数,执行return等过程,从而提高速度。

内联函数是代码被插入到调用者代码处的函数。内联函数也不是万能的,它的使用是有所限制的,它只适合函数体内简单的函数使用,不能包含复杂的结构和控制语句(如for while switch),并且内联函数本身不能直接调用递归函数(自己内部还调用自己的函数)。

两者的区别:

a、宏定义是在预处理阶段进行代码替换,而内联函数是在编译阶段插入代码;

b、宏定义没有类型检查,而内联函数有类型检查。

内联函数与普通函数的最大区别:在于其内部的实现方式上,普通函数在调用时有寻址过程,而内联函数不需要寻址。



16、定义常量谁更好?#define 还是const

效果虽然一样,但侧重点不同。

define 既可以替代常数值,又可以替代表达式,甚至是代码段,但容易出错;

const 的引入可以增强程序的可读性,使程序维护与调试更加方便。

主要区别:

a、define 只是用来进行单纯的文本替换,define的生命周期止于编译期,不分配内存空间,它存在于程序的代码段,在实际程序中,它只是一个常数,一个命令中的参数并没有实际存在;而const 常量存在于程序的数据段,并在堆栈中分配了空间,const 常量在程序中确确实实地存在,并且可以被调用和传递。

b、const 常量有数据类型,而 define 常量没有数据类型。

c、很多IDE 支持调试const定义的常量,而不支持define 定义的常量、\。



六、结构体与类

1、C语言中struct 和union 的区别是什么

struct (结构体)与union (联合体)是C语言中两种不同的数据结构。

区别:

a、联合体中所有成员共用一块地址空间,联合体的长度为其最长的成员的长度;而结构体中所有成员占用空间是累加的(需要考虑字节对齐)

b、对于联合体的不同成员赋值,将会对它的其它成员重写,而对结构体就不会。



2、C 和C++ 中struct 的区别是什么

C语言中struct 与C++ 中的struct 区别表现在以下三个方面:

a、C语言的struct 不能有函数成员,而C++ 的struct 可以有;

b、C语言的struct 中数据成员没有private、public和protected 访问权限的设定,而C++的struct 的成员有访问权限的设定。

c、C语言的struct 是没有继承关系的,而C++ 的struct 却有丰富的继承关系。



3、C++ 中struct 与class的区别是什么

如果没有多态和虚拟继承,在C++中,struct 和class 的存取效率完全相同。

两点区别:

a、默认继承权限,class 继承默认是private 继承,而struct 继承默认是 public 继承

b、class 还用于定义模板参数,就行typename, 但关键字struct 不用于定义模板参数。



七、位操作

1、一些结构声明中的冒号和数字是什么意思

C语言的结构体可以实现位段,它的定义形式是在一个定义的结构体成员后面加上冒号,然后是该成员所占的位数。位段的结构体必须是int 或者unsigned int 类型,不能是其他类型。



2、最有效的计算 2 乘以 8 的方法是什么

2<<3



3、如何实现位操作求两个数的平均值

(x & y) + ((x^y)>> 1)

(x & y)表示的是取出 x 与 y 二进制位数中都为 1 的所有位

(x^y)表示的是x 与 y 中有一个为 1 的所有位,右移一位相当为执行除以2运算。



4、unsigned int i = 3; printf(“%u\n”, i *-1)输出多少

4294967293,。 无符号的int值域为[0,4294967295]。



5、如何求解整型数的二进制表示中1 的个数

while(x){ countx++; x=x&(x-1)}



6、不能用sizeof,如何判断操作系统是16位还是32 位的

打印最大值,或者对0取反。



7、嵌入式编程中,什么是大端?什么是小端

大端模式:低地址存放高字节,高地址存放低字节

小端模式:低地址存放低字节,高地址存放高字节



8、考虑n 位二进制数,有多少个数中不存在两个相邻的1 

满足斐波拉契数列



9、不用除法操作符如何实现两个正整数的除法

位运算的知识:

a、常用的等式:-n = ~(n-1) = ~n + 1

b、获取整数n 的二进制中 最后一个 1:n&(-n) 或者 n&~(n-1)。例如, n=010100,则-n = 101100,n&(-n) =000100。

c、去掉整数n 的二进制中 最后一个 1:n&(n-1) 。例如, n=010100,则n-1 =010011,n&(n-1) =010000。

采用减法;采用移位操作。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息