笔试面试题记录(0x01) —— #define

来源:互联网 发布:手机音乐识别软件 编辑:程序博客网 时间:2024/05/21 15:49

一直感觉自己明白#define是怎么回事

直到迪普笔试遇到这道题:

设有以下宏定义
#define N 3 
#define Y(n) ((N+1)*n) 
则执行语句:z=2*((N+Y(5+1));后,z的值为(    )。        
A、 出错  
B、 42  
C、 48  
D、 54

define, 宏定义

define在程序运行之前,编译预处理时, 替换

比如:#define PI 3.1415926

在程序编译预处理的时候,将会把程序中所有的PI都替换成3.1415926

这样写的好处有很多, 比如可以方便程序修改, 在程序中用PI代替3.1415926这串数字也增加了程序的可读性



我觉得也许我的C根本没入门

当时觉得 2*(N+Y(5+1)) == 2 *(3 + (3 + 1) * 6) == 2 * 27 == 54

选了D

后来面试我的人,问我,这样define的写法, 和写成函数形式的区别

我答:define是在运行之前替换,而函数是运行时调用, 巴拉巴拉巴拉...

他说:那你怎么没直接替换呢?..

我    :......

他说:下次注意就行了,小问题。( 他以为我懂,以为我是笔误呢)

其实面试结束我也不明白我错哪了, 呵呵。


后来回到家里, 从网上看到了这道题, 才明白自己到底错在哪了


#define  就是在运行之前替换, 替换就是替换, 你就只需要替换就行

不需要做多余的操作 , 比如上题中, 我自己把 5 + 1 求出来了

替换就是替换, 替换就是替换, 替换就是替换, 所以你只需要替换即可

无论需要替换的是一个数字, 还是一个表达式

所以我们应该把 5+1 代替 Y(n)中的n , 而不是6

所以, 2*(N+Y(5+1)) == 2 *(3 + (3 + 1) *5 + 1) == 2 * 24 == 48

神奇了, 神奇之处在于, 把 5+1带入之后, 运算的优先级导致你不是简单的直接5+1了

而是要考虑其他运算符的优先级顺序


这也让我忽然想到了, 为什么之前很多人一直强调, 在#define后面, 用()

比如,  #define f(a) a+a  要写成  #define f(a)  ((a)+(a))

之前我一直认为多写这些括号是多余的, 现在看来,如果没有这些括号根本不对

看到这里也应该能很轻易想出 上面第一种写法 出错的 反例

你只需要让f(a)和其他数字N进行一次乘法运算就行了

比如, 你想要得到 N * (a + a) , 但是第一种解法得到的结果却是 N * a + a

至于里面(a)+(a)这里坚持加两个括号的原因:找个反例吧

反例是如果是(a)*(a) 而a代表的是一个加法表达式呢?

好像写的好啰嗦, 就到这吧

下面给出几个define的类似题目, 来自互联网。



01、下面程序的运行结果是 
#define ADD(x) x+x 
int main() 
{
int m=1, n=2, k=3; 
  int sum = ADD(m+n)*k;
  printf("sum=%d\n", sum);
  return 0;   
}    

A、sum=9    
B、sum=10    
C、sum=12  
D、sum=18  



02、下列程序执行后的输出结果是 
#define MA(x) x*(x-1) 
int main()
{
int a = 1, b = 2;
printf("%d\n", MA(1+a+b));
}    
A、6  
B、8  
C、10  
D、12  



03、以下程序的输出结果是 
#define f(x) x*x 
int main() 
{
int a=6, b=2, c; 
c = f(a) / f(b);
printf("%d\n",c); 
}    
A、9  
B、6  
C、36  
D、18  


04、以下程序运行后,输出结果是(    )。 
#define P 5.5 
#define S(X) P*X*X 
int main() 
{
int a=1, b=2;
printf("%.1lf\n", S(a+b)); 
}
A、49.5    
B、9.5  
C、22.0  
D、45.0  



05、以下程序的运行结果是
#define MIN(x,y) (x)<(y)?(x):(y) 
int main() 
{
int i=10, j=15, k; 
k = 10 * MIN(i,j); 
printf("%d\n",k);  
return 0;

A、10  
B、15  
C、100  
D、150  



06、从下列选项中选择不会引起二义性的宏定义是(    )。 

A) #define POWER(X) X*X    

B) #define POWER(X) (X)*(X)

C) #define POWER(X) (X*X)  

D) #define POWER(X) ((X)*(X))


key:

01 B note: m+n+m+n*k == 1 + 2 + 1 + 2 * 3 == 10

02 B note: 1+a+b*(1+a+b-1) == 8

03 C note: 6 * 6 / 2 * 2 == 36

04  B note: P * a + b * a + b == 5.5 * 1 + 2 * 1 + 2 == 9.5

05 B note: k = 10 * 10 < 15 ? 10 : 15 = 15

06 D



 附1:带参数宏与函数的区别(摘自清华大学C语言程序设计PPT)



 带参数的宏函数处理时间编译时 程序运行时参数类型无类型问题定义实参、形参类型处理过程不分配内存
简单的字符置换 分配内存
先求实参值 再代入形参程序长度变长不变运行速度不占运行时间调用和返回占时间










原创粉丝点击