Директива #define (C/C++)#define directive (C/C++)

#Define создает макрос, который представляет собой ассоциацию идентификатора или параметризованного идентификатора со строкой токена.The #define creates a macro, which is the association of an identifier or parameterized identifier with a token string. После определения макроса компилятор может подставить строку токена для каждого обнаруженного идентификатора в исходном файле.After the macro is defined, the compiler can substitute the token string for each occurrence of the identifier in the source file.

СинтаксисSyntax

#define токена идентификатора — строкаOPT#define identifier token-stringopt
идентификатор #define ( идентификаторOPT, ... , идентификаторOPT ) — строка снеявной строкой#define identifier ( identifieropt, ... , identifieropt ) token-stringopt

КомментарииRemarks

Директива #define заставляет компилятор заменить строку токена для каждого вхождения идентификатора в исходном файле.The #define directive causes the compiler to substitute token-string for each occurrence of identifier in the source file. Идентификатор заменяется только в том случае, если он формирует маркер.The identifier is replaced only when it forms a token. Это значит, что идентификатор не заменяется, если он присутствует в комментарии, в строке или в составе более длинного идентификатора.That is, identifier is not replaced if it appears in a comment, in a string, or as part of a longer identifier. Дополнительные сведения см. в разделе токены.For more information, see Tokens.

Аргумент строки токена состоит из ряда токенов, таких как ключевые слова, константы или полные инструкции.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 that follows the last token of the text.

A #define без строки токена удаляет вхождения идентификатора из исходного файла.A #define without a token-string removes occurrences of identifier from the source file. Идентификатор остается определенным и может быть проверен с помощью #if defined #ifdef директивы и.The identifier remains defined and can be tested by using the #if defined and #ifdef directives.

Вторая форма синтаксиса определяет макрос, подобный функции, с параметрами.The second syntax form defines a function-like macro with parameters. Эта форма допускает использование необязательного списка параметров, которые должны находиться в скобках.This form accepts an optional list of parameters that must appear in parentheses. После определения макроса каждое последующее вхождение идентификатора (неявноезначение,..., идентификаторOPT ) заменяется версией аргумента -строки токена , которая содержит фактические аргументы, подставляемые для формальных параметров.After the macro is defined, each subsequent occurrence of identifier( identifieropt, ..., identifieropt ) is replaced with a version of the token-string argument that has actual arguments substituted for formal parameters.

Формальные имена параметров отображаются в строке токена для обозначения мест, в которых заменяются фактические значения.Formal parameter names appear in token-string to mark the locations where actual values are substituted. Имя каждого параметра может встречаться несколько раз в строке токена, а имена могут отображаться в любом порядке.Each parameter name can appear multiple times 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 guarantees that complex actual arguments are interpreted correctly.

Формальные параметры в списке разделяются запятыми.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 (\) immediately 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 indicate a macro call. Фактические аргументы, которые следуют за экземпляром идентификатора в исходном файле, сопоставляются с соответствующими формальными параметрами в определении макроса.The actual arguments that follows an instance of identifier in the source file are matched to the corresponding formal parameters in the macro definition. Каждый формальный параметр в строке токена , не предшествующий оператору строковый ( # ), преобразования ( #@ ) или Token-Place ( ## ) или не заканчивающийся ## оператором, заменяется соответствующим фактическим аргументом.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.)

Следующие примеры макросов с аргументами иллюстрируют вторую форму синтаксиса #define :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 one time 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 one time. (См. примеры в разделе Оператор, посвященный вставлению токена (# #).)(See the examples under Token-Pasting Operator (##).)

Директива #undef приводит к тому, что определение препроцессора идентификатора забывается.The #undef directive causes an identifier's preprocessor definition to be forgotten. Дополнительные сведения см. в директиве #undef .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.

Вторая #define макроса с тем же именем создает предупреждение, если вторая последовательность токенов не совпадает с первой.A second #define for a macro with the same name generates a warning unless the second token sequence is identical to the first.

Блок, относящийся только к системам MicrosoftMicrosoft Specific

Если новое определение синтаксически совпадает с исходным, Microsoft C и C++ позволяют переопределить макрос.Microsoft C/C++ lets you redefine a macro if the new definition is syntactically identical to the original definition. Другими словами, два определения могут иметь разные имена параметров.In other words, the two definitions can have different parameter names. Это поведение отличается от ANSI C, которое требует лексического идентичности двух определений.This behavior differs from ANSI C, which requires that the two definitions be lexically identical.

Например, следующие два макроса идентичны, за исключением имен параметров.For example, the following two macros are identical except for the parameter names. ANSI C не допускает такое переопределение, но Microsoft C/C++ компилирует его без ошибок.ANSI C does not allow such a redefinition, but Microsoft C/C++ compiles it without error.

#define multiply( f1, f2 ) ( f1 * f2 )
#define multiply( a1, a2 ) ( a1 * a2 )

С другой стороны, следующие два макроса неидентичны и приводят к выдаче предупреждения в Microsoft C и C++.On the other hand, the following two macros are not identical and will generate a warning in Microsoft C/C++.

#define multiply( f1, f2 ) ( f1 * f2 )
#define multiply( a1, a2 ) ( b1 * b2 )

Завершение блока, относящегося только к системам МайкрософтEND Microsoft Specific

В этом примере показана директива #define :This example illustrates the #define directive:

#define WIDTH       80
#define LENGTH      ( WIDTH + 10 )

Первый оператор определяет идентификатор WIDTH как целочисленную константу 80, а затем 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. Каждое вхождение LENGTH заменяется на (WIDTH + 10).Each occurrence of LENGTH is replaced by (WIDTH + 10). В свою очередь, каждое вхождение WIDTH + 10 заменяется выражением (80 + 10).In turn, each occurrence of WIDTH + 10 is replaced by the expression (80 + 10). Скобки вокруг WIDTH + 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;

что равно 1800.which evaluates to 1800. Без скобок результат будет следующим:Without parentheses, the result is:

var = 80 + 10 * 20;

результатом вычисления которого является 280.which evaluates to 280.

Блок, относящийся только к системам MicrosoftMicrosoft Specific

Определение макросов и констант с помощью параметра компилятора /d аналогично использованию директивы предварительной обработки #define в начале файла.Defining macros and constants with the /D compiler option has the same effect as using a #define preprocessing directive at the start of your file. С помощью параметра /D можно определить до 30 макросов.Up to 30 macros can be defined by using the /D option.

Завершение блока, относящегося только к системам МайкрософтEND Microsoft Specific

См. такжеSee also

Директивы препроцессораPreprocessor directives