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.