网站地图
hnsjyk999.com
三九百科 包罗万象
#define 发布于:

#define是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

在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);

a=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__

文件内容

#endif


相关文章推荐:
C语言 | #undef | stdio.h | 宏定义 | 预处理命令 | c语言 |