When I read someone’s code I find that he bothered to write an explicite type cast.
#define ULONG_MAX ((unsigned long int) ~(unsigned long int) 0)
When I write code
1 #include<stdio.h>
2 int main(void)
3 {
4 unsigned long int max;
5 max = ~(unsigned long int)0;
6 printf("%lx",max);
7 return 0;
8 }
it works as well. Is it just a meaningless coding style?
The code you read is very bad, for several reasons.
First of all user code should never define
ULONG_MAX. This is a reserved identifier and must be provided by the compiler implementation.That definition is not suitable for use in a preprocessor
#if. The_MAXmacros for the basic integer types must be usable there.(unsigned long)0is just crap. Everybody should just use0UL, unless you know that you have a compiler that is not compliant with all the recent C standards with that respect. (I don’t know of any.)Even
~0ULshould not be used for that value, sinceunsigned longmay (theoretically) have padding bits.-1ULis more appropriate, because it doesn’t deal with the bit pattern of the value. It uses the guaranteed arithmetic properties of unsigned integer types.-1will always be the maximum value of an unsigned type. So~may only be used in a context where you are absolutely certain thatunsigned longhas no padding bits. But as such using it makes no sense.-1serves better.“recasting” an expression that is known to be
unsigned longis just superfluous, as you observed. I can’t imagine any compiler that bugs on that.Recasting of expression may make sense when they are used in the preprocessor, but only under very restricted circumstances, and they are interpreted differently, there.
Here the value on the left evalues to
UINTMAX_MAXin the preprocessor and in later compiler phases. Sowould be an appropriate definition for a compiler implementation.
To see the value for the preprocessor, observe that there
(uintmax_t)is not a cast but an unknown identifier token inside()and that it evaluates to0. The minus sign is then interpreted as binary minus and so we have0-1ULwhich is unsigned and thus the max value of the type. But that trick only works if the cast contains a single identifier token, not if it has three as in your example, and if the integer constant has a-or+sign.