Are C macros implicitly cast?

c, c++, c-preprocessor, macros, types

Solution

The preprocessor expands macros before the compiler even sees anything. We can see that preprocessing numbers don't have a type by going to the draft C99 standard section `6.4.8` Preprocessing numbers which says:

A preprocessing number does not have type or a value; it acquires both after a successful conversion (as part of translation phase 7) to a floating constant token or an integer constant token.

The same section in the draft C++ standard is `2.10`.

As we can see in C preprocessor Wikipedia article macro expansion happens in phase 4.

The conversion of integer constants in C terminology and integer literals in C++ terminology is covered in the draft C99 standard section `6.4.4.1` Integer constants and the following table in paragraph 5 which says:

The type of an integer constant is the first of the corresponding list in which its value can be represented

                                           Octal or Hexadecimal
Suffix        Decimal Constant                 Constant
---------------------------------------------------------------------------
none          int                           int
              long int                      unsigned int
              long long int                 long int                                
                                            unsigned long int
                                            long long int
                                            unsigned long long int
---------------------------------------------------------------------------
u or U        unsigned int                  unsigned int
              unsigned long int             unsigned long int
              unsigned long long int        unsigned long long int
---------------------------------------------------------------------------
l or L        long int                      long int
              long long int                 unsigned long int
                                            long long int
                                            unsigned long long int
---------------------------------------------------------------------------
Both u or U   unsigned long int             unsigned long int
and  l or L   unsigned long long int        unsigned long long int
---------------------------------------------------------------------------
ll or LL      long long int                 long long int
                                            unsigend long long int
---------------------------------------------------------------------------
Both u or U   unsigned long long int        unsigned long long int
and  ll or LL
---------------------------------------------------------------------------

Table is a modified version of the one from this answer. The section that covers this in the draft C++ standard is section `2.14.2` which also has a similar table.

So in your example `40` has no suffix and is a decimal constant and the first type it can be represented from that section of the table is int.

At this point we now end up with the effects of using `40` with the `<` operator. Since `i` and `40` are both arithmetic types then the usual arithmetic conversions will be performed, which in this case will still be int. For C99 this is covered in section `6.3.1.8` and C++ section 5.

Problem

I've searched SO, but haven't found an answer to this specific questions. Forgive me if it's already been answered. If you have the following: ``` #define MACRO 40 ``` You don't assign it to a variable you use it in a loop: ``` for(int i = 0; i < MACRO; i++) {... ``` The perprocessor then creates: ``` for(int i = 0; i < 40; i++) {... ``` Would the compiler then implicitly cast it to an int since the comparison is with type `int i`? I've looked at this question Type of #define variables, and quite a few answers down Edgar Bonet implies that there is an order in which the compiler chooses how to treat the macro? This question, How does C++ implicitly cast arguments to a comparator such as <?, was also suggested, but only describes how implicit casting works with a comparison with two types. Since a macro doesn't really have a type I'm not sure if this applies.

Original source

Related problems