enum
(2)Enumeration constant(列舉常數)
C語言中,當要定義一個常數時,可以利用巨集或列舉,如下:
#define MAX 10
or
enum { MAX = 10 };	//unnamed enumeration(無名列舉)
C++中,當要定義一個常數時,可以利用C語言的方法,而C++中也有提供另一個方法
#define MAX 10
or
enum { MAX = 10 };
or
int const MAX = 10;   or const int MAX = 10;	//const objects
為什麼不直接在程式中直接寫常數在所需要的地方呢?
有二個常見的原因
•減少程式碼的修改:假設程式中有一百個地方要從原本的10改為20,如果真得一個一個改
                    改到手的抽筋了!!當然,也可以直接利用編譯器提供的取代功能來使用。
               	    但寫的人敢保證,不會取代到其它的數值嗎?(1001000之類的)
	                如果使用以上任何一種宣告常數的方法,只需要更改常數宣告的地方即可。
•數字意思文字化:在程式突然出現一個1027,誰知道是什麼意思呢?如果10是表示陣列的大小,
                  這樣寫可能會比較讓別人瞭解 #define ARRAY_SIZE 10 對吧!

那利用defineenumconst有什麼差別呢?基本只談論差別不談論優劣
(a)define
說到define就要先談起何謂Preprocessor(前置處理器),說到Preprocessor就要談起一個source file
是編譯的,過程是如此的:
	C/C++ source file ==> Preprocessor ==> Compiler
Preprocessor是根據source file中的Preprocessor directive(前置處理指令;前置指令)來執行各種動作,再將
執行之後的source file交由Compiler進行compile的動作。Preprocessor directive的指令如下:
#define   #undefine   #include   #if   #ifdef   #ifndef   #else   #elif   #endif   #line   #error   #pragma
#define的語法是如此的(一般都以大寫來表示,但沒有規定一定要大寫)

	#define DEFINE_SYMBOL SYMBOL_CONTENT

DEFINE_SYMBOL : 定義一個名稱代表SYMBOL_CONTENT的值或表示式
SYMBOL_CONTENT:定義DEFINE_SYMBOL所要表示的值或表示式,可以沒有SYMBOL_CONTENT
接下來從例子中學習會比較快:
	#include<stdio.h>
	#include<math.h>

	#define PI 4*atan(1)
	#define SIN(X) sin((X)*PI/180)

	void main()
	{

		printf("%f\n",SIN(45));
	}
以上程式經過preprocessor處理之後的程式如下:
	void main()
	{
		printf("%d\n",sin((45)*4*atan(1)/180));
	}
做的動作是"取代"。這就是利用#define來產生常數的資料方式。
(b)enum
在前一篇文章介紹過,enum在編譯期間(at compile-time)已經建立起,其列舉元會被視為常數。
但請注意之前說過列舉元設定的值必須是常數值或另一個列舉元,所以無法像這樣:enum { PI = 4 * atan(1) };
舉二個應用enum的例子:

	()用來class中:
	class Stack
	{
		private:
			enum { SIZE = 20 };
			int stack[SIZE];
			int top;
		public:
			int push(const int& element) ;
			int pop() const;
			...
	}
	()
	enum DIM_SIZE { ROW = 20 , COLUMN = 30 };
	void main()
	{
		int iArray[ROW][COLUMN];
		...
		...
	}
(c)const
const必須一開始就被初始化,若沒有初始化時,編譯器會產生錯誤的訊息,告知const物件必須初始化
接著來看const的產生方式,以下的結果是在Release build時所產生的ASM碼,不是Debug build時所產生的ASM
碼,Release buildDebug build有什麼差別呢?差別在於
Debug build會產生全部變數、表示式、...等的Debug資訊(ASM碼、...),並且不做optimization(優化)
Release build並不會產生Debug所需要的information,並且會做optimization的動作,讓程式的效率更好更小
一般來說,要觀看C/C++程式碼真正編譯之後的動作,是看Release build之後的ASM碼。
在要如何在Release buildDebug呢?需要做一些設定,參考這一篇文章:Debugging a Release Build
接下來正式來看以下這段程式碼:
           const int *pctr=0;
                const int num = 20;
                pctr = &num;
                cout<<*pctr;
00401000   push      14h
00401002   mov       ecx,offset std::cout (00427318)
00401007   call        std::basic_ostream<char,std::char_traits<char> >::operator<< (00401010)
所產生的ASM碼,其實只有最後一行cout,其餘都已在compile-time的時候被compilercompile掉了!
編譯器知道常數num20,而pctr指向它,所以*pctr就直接取代成20,這是一個很smart compiler!
常數的性質在編譯期間就已被處理完畢,所以在run-time時是不佔有位置的。
而若使用Debug build,得到的ASM碼:
           const int *pctr=0;
00401554   mov         dword ptr [pctr],0
                const int num = 20;
0040155B   mov         dword ptr [num],14h
                pctr = &num;
00401562   lea         eax,[num]
00401565   mov         dword ptr [pctr],eax
                cout<<*pctr;
00401568   mov         ecx,dword ptr [pctr]
0040156B   mov         edx,dword ptr [ecx]
0040156D   push        edx
0040156E   mov         ecx,offset std::cout (00454828)
00401573   call        @ILT+245(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004010fa)

會發現每一行都會產生相對應的ASM碼,這是因為Debug build必須加上debug所需要資訊及沒有做優化的動作。
continue...
回目錄
Written By James On 2004/02/08 

Hosted by www.Geocities.ws

1