複製鏈接
請複製以下鏈接發送給好友

#define

鎖定
#define是 C語言 和 C++ 中的一個預處理指令,其中的“#”表示這是一條預處理命令·。凡是以“#”開頭的均為預處理命令,“define”為定義命令,“標識符”為所定義的宏名。#define的部分運行效果類似於word中的ctrl+F替換,與常量const相比有着無法替代的優勢。
中文名
#define
外文名
define
所屬學科
c
類    型
C語言
宏    名
標識符

#define定義解釋

The define Directive
You can use the #define directive to give a meaningful name to a constant in your program. The two forms of the syntax are:
Syntax
define identifier token-stringopt
define identifier[( identifieropt, ... , identifieropt )] token-stringopt
__________________________________________
以上是最主要的語法,説明一下,其他在運用時再理解也不遲:
語法一:
#define 標識符 被標識符代表的字符串 //這種用法很簡單,就是一種替換.
語法二:
#define 標識符[(參數1,.....,參數n)] 被標識符代表的字符串 //其中,在"被標識符代表的字符串"中出現的形參將在使用時被實參替代. 就像寫函數一樣.
補充一點: 在用#define 定義時 ,可以用斜槓("\") 續行.與vb中的下劃線(" _")作用同.
比如:
#define add1( x, y ) ( x + y)
也可以表示成 :
#define add1(x,y) \
(x + y )
__________________________________________
The #define directive substitutes token-string for all subsequent occurrences of an identifier in the source file. The identifier is replaced only when it forms a token. (SeeC++ Tokens in the C++ Language Reference.) For instance, identifier is not replaced if it appears in a comment, within a string, or as part of a longer identifier.
A #define without a token-string removes occurrences of identifier from the source file. The identifier remains defined and can be tested using the #if defined and #ifdef directives.
The token-string argument consists of a series of tokens, such as keywords, constants, or complete statements. One or more white-space characters must separate token-string from identifier. This white space is not considered part of the substituted text, nor is any white space following the last token of the text.
Formal parameter names appear in token-string to mark the places where actual values are substituted. Each parameter name can appear more than once in token-string, and the names can appear in any order. The number of arguments in the call must match the number of parameters in the macro definition. Liberal use of parentheses ensures that complicated actual arguments are interpreted correctly.
The second syntax form allows the creation of function-like macros. This form accepts an optional list of parameters that must appear in parentheses. References to the identifier after the original definition replace each occurrence of identifier( identifieropt, ..., identifieropt ) with a version of the token-string argument that has actual arguments substituted for formal parameters.
The formal parameters in the list are separated by commas. Each name in the list must be unique, and the list must be enclosed in parentheses. No spaces can separate identifier and the opening parenthesis. Use line concatenation — place a backslash (\) before the newline character — for long directives on multiple source lines. The scope of a formal parameter name extends to the new line that ends token-string.
When a macro has been defined in the second syntax form, subsequent textual instances followed by an argument list constitute a macro call. The actual arguments following an instance of identifier in the source file are matched to the corresponding formal parameters in the macro definition. Each formal parameter in token-string that is not preceded by a stringizing (#), charizing (#@), or token-pasting (##) operator, or not followed by a ## operator, is replaced by the corresponding actual argument. Any macros in the actual argument are expanded before the directive replaces the formal parameter. (The operators are described in Preprocessor Operators.)
The following examples of macros with arguments illustrate the second form of the #define syntax:
// Macro to define cursor lines
#define CURSOR(top, bottom) ((top) << 8) | bottom))
// Macro to get a random integer with a specified range
#define getrandom(min, max) \
((rand()%(int)(((max) + 1)-(min)))+ (min))
Arguments with side effects sometimes cause macros to produce unexpected results. A given formal parameter may appear more than once in token-string. If that formal parameter is replaced by an expression with side effects, the expression, with its side effects, may be evaluated more than once. (See the examples under Token-Pasting Operator (##).)
The #undef directive causes an identifier’s preprocessor definition to be forgotten. See The #undef Directive for more information.
If the name of the macro being defined occurs in token-string (even as a result of another macro expansion), it is not expanded.
A second #define for a macro with the same name generates an error unless the second token sequence is identical to the first.
Microsoft Specific
Microsoft C/C++ allows the redefinition of a macro, but generates a warning, provided the new definition is lexically identical to a previous definition. ANSI C considers macro redefinition an error. For example, these macros are equivalent for C/C++ but generate warnings:
#define test( f1, f2 ) ( f1 * f2 )
#define test( a1, a2 ) ( a1 * a2 )
END Microsoft Specific
This example illustrates the #define directive:
#define WIDTH 80
#define LENGTH ( WIDTH + 10 )
The first statement defines the identifier WIDTH as the integer constant 80 and defines LENGTH in terms of WIDTH and the integer constant 10. Each occurrence of LENGTH is replaced by (WIDTH + 10). In turn, each occurrence of WIDTH + 10 is replaced by the expression (80 + 10). The parentheses around WIDTH + 10 are important because they control the interpretation in statements such as the following:
var = LENGTH * 20;
After the preprocessing stage the statement becomes:
var = ( 80 + 10 ) * 20;
which evaluates to 1800. Without parentheses, the result is:
var = 80 + 10 * 20;
which evaluates to 280.
Microsoft Specific
Defining macros and constants with the /D compiler option has the same effect as using a #define preprocessing directive at the beginning of your file. Up to 30 macros can be defined with the /D option.
END Microsoft Specific
#define GPEBLT_FUNCNAME(basename) (SCODE (GPE::*)(struct GPEBltParms *))&GPE::##basename
在#define中,標準只定義了#和##兩種操作。#用來把參數轉換成字符串,##則用來連接前後兩個參數,把它們變成一個字符串。
#include <stdio.h>
#define paster( n ) printf( "token " #n" = %d\n ", token##n )
	int main()
{
	int token9=10;
	paster(9);
	return 0;
}
//輸出為
//[leshy@leshy src]$ ./a.out
//token 9 = 10

#define主要作用

在C或C++語言源程序中允許用一個標識符來表示一個字符串,稱為“”。被定義為“宏”的標識符稱為“宏名”。在編譯預處理時,對程序中所有出現的“宏名”,都用宏定義中的字符串去代換,這稱為“宏代換”或“宏展開”。宏定義是由源程序中的宏定義命令完成的。宏代換是由預處理程序自動完成的。
在C或C++語言中,“宏”分為有參數和無參數兩種。
無參宏定義
無參宏的宏名後不帶參數。
其定義的一般形式為:
#define 標識符 字符串
其中的“#”表示這是一條預處理命令。凡是以“#”開頭的均為預處理命令。“define”為宏定義命令。“標識符”為所定義的宏名。“字符串”可以是常數、表達式、格式串等。
例如:
#define M (a+b)
它的作用是指定標識符M來代替表達式(a+b)。在編寫源程序時,所有的(a+b)都可由M代替,而對源程序作編譯時,將先由預處理程序進行宏代換,即用(a+b)表達式去置換所有的宏名M,然後再進行編譯。
程序1:
#define M (a+b)
main()
{
	int a{3},b;
	printf("input a number: ");
	scanf("%d",&b);
	s=M*M;
	printf("s=%d\n",a);
}
上例程序中首先進行宏定義,定義M來替代表達式(a+b),在 s= M * M 中作了宏調用。在預處理時經宏展開後該語句變為: S=(a+b)*(a+b)
但要注意的是,在宏定義中表達式(a+b)兩邊的括號不能少。否則會發生錯誤。
如當作以下定義後:#difine M (a)+(b)
在宏展開時將得到下述語句:S= (a)+(b)*(a)+(b)
對於宏定義還要説明以下幾點:
1. 宏定義是用宏名來表示一個字符串,在宏展開時又以該字符串取代宏名,這只是一種簡單的代換,字符串中可以含任何字符,可以是常數,也可以是表達式,預處理程序對它不作任何檢查。如有錯誤,只能在編譯已被宏展開後的源程序時發現。
2. 宏定義不是説明或語句,在行末不必加分號,如加上分號則連分號也一起置換。
3. 宏定義必須寫在函數之外,其作用域為宏定義命令起到源程序結束。如要終止其作用域可使用#undef命令。
(有關#undef 請查閲其他資料)
帶參宏定義
c語言允許宏帶有參數。在宏定義中的參數稱為形式參數,在宏調用中的參數稱為實際參數對帶參數的宏,在調用中,不僅要宏展開,而且要用實參去代換形參。
帶參宏定義的一般形式為:
#define 宏名(形參表) 字符串
在字符串中含有各個形參。
帶參宏調用的一般形式為:
宏名(形參表)
例如:
#define M(y) ((y)*(y)+3*(y)) /*宏定義*/
....
k=M(5); /*宏調用*/
....
在宏調用時,用實參5去代替形參y,經預處理宏展開後的語句為:
k=5*5+3*5
程序2:
#define MAX(a,b) (a>b)?a:b
main()
{
	int x,y,max;
	printf("input two numbers: ");
	scanf("%d%d",&x,&y);
	max=MAX(x,y);
	printf("max=%d\n",max);
}
上例程序的第一行進行帶參宏定義,用宏名MAX表示條件表達式(a>b)?a:b,形參a,b均條件表達式中。程序第七行max=MAX(x,y)為宏調用,實參x,y,將代換形參a,b。宏展開後該語句為:
max=(x>y)?x:y;
用於計算x,y中的大數。
#define 條件編譯
頭文件(.h)可以被頭文件或C文件包含
重複包含(重複定義)
由於頭文件包含可以嵌套,那麼C文件就有可能包含多次同一個頭文件,就可能出現重複定義的問題的。
通過條件編譯開關來避免重複包含(重複定義)
例如
#ifndef __headerfileXXX__
#define __headerfileXXX__
文件內容