一日,老婆下班回來,說要測試一下我的C語言還記得多少,頓時驚起一身冷汗,哈哈,這個東西已有很久沒有用了。細節怕是……。接下問題開始下文。
二、問題描述
以下兩種程序寫法有何不同:
1.
#include <stdio.h>
#define sq(y) ((y)*(y))
void main (void)
{
int i =1 ;
while(i<=5)
printf("%d/n",sq(i++));
}
2.
#include <stdio.h>
int sq(int y)
{
return y*y;
}
void main (void)
{
int i =1 ;
while(i<=5)
printf("%d/n",sq(i++));
}
三、問題解釋
乍一看感覺沒什麼,但一思考,想法還是很多:
- 這兩段代碼一個採用了函數,另一個使用了宏定義。函數的參數類型是限制死的,而宏就可以隨便了。
- 因爲宏定義在編譯時是要進行替換的,所以還有一個差別就在這個i++上了,宏一個每次循環i加兩次,而函數只加一次了,所以兩個的執行結果肯定不同。
1,9,25
彙編代碼如下:
mov eax, DWORD PTR _i$[ebp]
imul eax, DWORD PTR _i$[ebp]
mov DWORD PTR -8+[ebp], eax
mov ecx, DWORD PTR -8+[ebp]
push ecx
push OFFSET FLAT:??_C@_03HMFC@?$CFd?6?$AA@ ; `string'
mov edx, DWORD PTR _i$[ebp]
add edx, 1
mov DWORD PTR _i$[ebp], edx
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
call _printf
而在使用sco unix 的編譯環境編譯後的執行結果則大不相同(這個是符合一般的想法的)。所以這種寫法是不可取的,因爲移植性沒有。所以儘量不能這樣寫((i++)*(i++))。
使用宏這種方式有什麼優勢呢,就是減少了函數執行時的性能消耗,這個對於嵌入式系統來說可是很關鍵的。個人認爲這點可能比出題人設計的無聊的無確定結果的題目更應該被人理解和記住。
歡迎不吝賜教。