Device Monitoring Studio - Monitor, log and analyze data coming through PC ports and connections
Download Device Monitoring Studio Hide this button

#define Directive

#define directive lets you define preprocessor-time constants and macros.

Syntax:

#define id [token-string]

or

#define id([id, [id, […]]) [token-string]

A macro declaration must end on the same line. If you need to continue on the next line, finish a line with a backslash character:

#define MY_STRING "This is a start of the long "   \
          "long long " \
          "string"    // the end of macro declaration

Defining Constants

In its first form, #define creates a preprocessor-time constants. For example:

#define MAX_LENGTH 5          

This declaration will instruct the preprocessor to scan the source file and replace all occurrences of MAX_LENGTH with 5. The preprocessor is smart enough to only perform a replace when MAX_LENGTH is used as an identifier, that is, it will transform the following code fragment:

// This example uses MAX_LENGTH:
struct A
{
    int array[MAX_LENGTH];
    const int MaxLength = MAX_LENGTH;
    $assert(MaxLength == MAX_LENGTH, "Error with MAX_LENGTH");
};

into the following:

// This example uses MAX_LENGTH:
struct A
{
    int array[5];
    const int MaxLength = 5;
    $assert(MaxLength == 5, "Error with MAX_LENGTH");
};

As you see, substitution had not occurred in comment and in string. All other occurrences have been replaced.

A constant may be more complex, for example:

#define MAX_LENGTH (2 + 5)

Note the use of parenthesis in order to prevent operator precedence errors.

Defined constants may refer to constants defined before:

#define SECOND 10000000
#define MINUTE (60 * SECOND)

The following form:

#define SOME          

will only define a constant, without assigning it a particular value. If occurred in a text, it gets removed from it. However, you may successfully test such constant within the #ifdef directive or using a defined() operator:

#define INCLUDE_STRUCT_A
// …
#ifdef INCLUDE_STRUCT_A
struct A
{
    // …
};
#endif

By convention, macros and preprocessor constants are named with uppercase letters.

Defining Macros

The second form of the directive is used to define macros:

#define ADD(x,y) ((x) + (y))          

The preprocessor will not only perform a replace, but also will perform a parameter substitution:

ADD(7,8)        // will be replaced with ((7) + (8))
ADD(n,-1)       // will be replaced with ((n) + (-1))

Macros may contain any number of parameters:

#define MAX(a,b) ((a) > (b) ? (a) : (b))

Variadic Macros

Device Monitoring Studio supports variadic macros. To use variadic macros, the ellipsis may be specified as the final formal argument in a macro definition, and the replacement identifier __VA_ARGS__ may be used in the definition to insert the extra arguments. __VA_ARGS__ is replaced by all of the arguments that match the ellipsis, including commas between them.

#undef Directive

An #undef directive is used to remove the macro definition.

Syntax:

#undef id          

Example:

#define MAX_LENGTH 5
struct A
{
    int array[MAX_LENGTH];
};

#undef MAX_LENGTH
struct B
{
    // compile-time error, "MAX_LENGTH" identifier not found 
    // (preprocessor did not replace it with "5")
    int array[MAX_LENGTH];
};