I occasionally will come across an integer type (e.g. POSIX signed integer type off_t
) where it would be helpful to have a macro for its minimum and maximum val
Quick answers only:
#define UINT_WHATEVER_T_MAX ( ~ (uint_whatever_t) 0 )
looks OK to me, the preference for -1 is that uint_whatever_t = -1;
is more concise than uint_whatever_t = ~(uint_whatever_t)0;
(CHAR_BIT * sizeof(t))
looks not strictly conforming to me. You're right about padding bits, so this value might be considerably more than the width of the type unless Posix says otherwise about off_t
.
In contrast, the fixed-width integer types in C99 must not have padding bits, so for intN_t
you're on firmer ground using the size to deduce the width. They're also guaranteed two's complement.
That would seem to imply that only those three listed signed number representations can be used. Is the implication correct
Yes. 6.2.6.2/2 lists the three permissible meanings of the sign bit, and hence the three permissible signed number representations.
is the sign bit guaranteed to always be one more significant than the most significant value bit
It's indirectly required to be more significant than the value bits, by the fact (6.2.6.2/2 again) that "Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type". So the value bits must be a contiguous range starting at the least significant.
However, you can't portably set just the sign bit. Read 6.2.6.2/3 and /4, about negative zeros, and note that even if the implementation uses a representation that has them in principle, it doesn't have to support them, and there's no guaranteed way of generating one. On a sign+magnitude implementation, the thing you want is a negative zero.
[Edit: oh, I misread, you only need to generate that value after you've ruled out sign+magnitude, so you could still be OK.
To be honest, it sounds a bit numpty to me if Posix has defined an integer type and not provided limits for it. Boo to them. I'd probably go with the old, "porting header" approach, where you put the thing that probably works everywhere in a header, and document that someone should probably check it before compiling the code on any freakish implementations. Compared with what they normally have to do to get anybody's code to work, they'll happily live with that.]