Mark said:
Should not the usual arithmetic conversion apply to this expression?
Certainly, but they don't help.
In this macro 60, 60 and 24 are of integer type, and 365 is of
unsigned long, which would make integral constants be converted to
unsigned long. Isn't it true?
No.
BTW, all four constants are of integer type. 60, 60, and 24 are
of type int, and 365UL is, as you say, of type unsigned long.
(It's important to remember than "integer" and "int" are not
synonymous; int is one of several integer types.)
How do you know that the expression is evaluated in exactly this
order?
I didn't say it was evaluated in any particular order. Parentheses
denote grouping, that is, which operands are associated with which
operators; they don't control order of evaluation.
In the abstract machine, 60 is multiplied by 60, yielding the
value 3600 of type int. Then that's multiplied by 24, yielding the
value 86400 of type int -- which may or may not be representable.
Only then does the unsigned long value 365UL come into play,
causing 86400 to be promoted from int to unsigned long before
the final multiplication.
Of course the compiler is free to do whatever reordering and
precalculation it likes -- as long as the final result meets the
standard's requirements. If INT_MAX >= 86400, the
expression will almost certainly be evaluated at compile time
to a constant 31536000UL.
Here's a program that demonstrates the issue if int is 32
bits and unsigned long long is 64 bits:
#include <stdio.h>
#include <limits.h>
#define WRONG (30000 * 30000 * 24 * 365ULL)
#define RIGHT (30000ULL * 30000 * 24 * 365)
int main(void)
{
printf("int is %d bits\n",
(int)sizeof(int) * CHAR_BIT);
printf("unsigned long long is %d bits\n",
(int)sizeof(unsigned long long) * CHAR_BIT);
printf("WRONG = %llu\n", WRONG);
printf("RIGHT = %llu\n", RIGHT);
return 0;
}
gcc produces a warning:
c.c: In function ‘main’:
c.c:14: warning: integer overflow in expression
and the program produces the following output:
int is 32 bits
unsigned long long is 64 bits
WRONG = 45684684800
RIGHT = 7884000000000
Note that the behavior is actually undefined; 45684684800 is the
result that happens to be generated under this implementation.