5

I want to compile code conditionally depending on the size of an integer, but I didn't quite find a way to determine the size of an integer in the preprocessor stage.

One idea is using the INT_MAX and comparing it to a constant:

#if INT_MAX >= 9223372036854775807UL
    printf("64 bit\n");
#elif INT_MAX >= 2147483647UL
    printf("32 bit\n");
#else
    printf("16 bit\n");
#endif

But I don't think it is guaranteed that a UL literal can be that large. And ULL is not available in C89 as far as I know.

So do you have any suggestions on how to solve this problem. Is there a macro that contains the size of int in some standard header maybe?

Edit:

Not a duplicate of this question because I don't actually need a generic sizeof and I don't want to print it. I only need to distinguish between distinct integer sizes for conditional compilation.

FSMaxB
  • 2,280
  • 3
  • 22
  • 41
  • Interesting question. In all the projects I have done I have that information available via the build system. Eg there are defines that are put in by the build system to give information such as ARM, INTEL, 32bit or 64bit etc. e.g. I can go #ifdef(SYSTEM_32BIT) to determine if its 32 bit etc. However if you want some code that is independent of any build system (e.g. a shared library source code that could go anywhere) then this won't work. You could use all the built in #defines of each compiler to figure it out but the would be pretty tedious. Your idea is probably ok. But check small first – waterjuice Nov 04 '16 at 04:51
  • There isn't a way to do that other than along the lines that you're proposing. In fact, there isn't another way in C99 or C11 either. And you're right that 2^63-1 isn't necessarily allowed by the preprocessor. Maybe the best way is to compile code that produces the sizes you need? Note that specific compilers may well provide the information in their own specific ways (and generally that means different compilers do it different ways, so portability isn't helped very much). – Jonathan Leffler Nov 04 '16 at 04:51
  • 1
    e.g.: Check if INT_MAX == (whatever it is in 16bit :-) ) first, then you don't need to worry about the 32bit constant being too large on some systems – waterjuice Nov 04 '16 at 04:52
  • why don't check for `sizeof(int)*CHAR_BIT`? – phuclv Nov 04 '16 at 05:45
  • 1
    @LưuVĩnhPhúc: `sizeof` isn't resolved during preprocessing. – alk Nov 04 '16 at 06:04
  • Possible duplicate of [How can I print the result of sizeof() at compile time in C?](http://stackoverflow.com/questions/20979565/how-can-i-print-the-result-of-sizeof-at-compile-time-in-c) – phuclv Nov 04 '16 at 06:08
  • @LưuVĩnhPhúc I don't think that dupe matches; it's about static assertions, and this is about conditional compilation, even if there are some similarities. – user694733 Nov 04 '16 at 07:19
  • Have you considered using configuration define to select size manually? It's usually easier to use that in preprocessor conditions, and you can use static assertion to detect that it's correctly set by user. – user694733 Nov 04 '16 at 07:30
  • When building within Linux (for a kernel module for example) the definition of INT_MAX contains a cast and therefore causes a warning and failure. That is, `#if INT_MAX == 0` will look like `#if ((int)(~0U>>1)) == 0`. But, the `int` will not be recognized as the type `int`. Instead it will be treated as an undefined symbol called `int`, which will have `0` (zero) substituted. This would result in bad syntax in the conditional expression, unexpectedly. I don't know if the kernel violates any laws about defining INT_MAX. For most people it won't come up. – cardiff space man Feb 15 '19 at 01:31

1 Answers1

7

Testing the smaller values first should work, since the preprocessor uses shortcut evaluation on #if statements:

#if INT_MAX == 32767
    #error 16 bits
#elif INT_MAX == 2147483647
    #error 32 bits
#elif INT_MAX == 9223372036854775807
    #error 64 bits
#else
    #error "What kind of weird system are you on?"
#endif
nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • I think I will go with this and fallback to 16 bits in the else case. – FSMaxB Nov 04 '16 at 07:54
  • 2
    @FSMaxB I don't think it makes sense to fallback back to 16-bits. You have already tested it, and it didn't pass. Better for code to clearly fail, than create possibly incorrect code. – user694733 Nov 04 '16 at 08:21
  • @user694733 In my case I might get away with it, because it doesn't break the code, only makes the performance really slow in some cases. The reason I'm doing this in the first place is for preventing undefined behavior in cases that the integer type is too small. – FSMaxB Nov 04 '16 at 12:36
  • The "else" case shouldn't actually happen on any sane system. INT_MAX is specified (on unix anyway) to be an #if-testable quantity, and I'd be surprised (as might you) if you ran into a system where int was not 16, 32 or 64-bits in size. – nneonneo Nov 04 '16 at 13:21