1

I would like to do the following, but the compiler doesn't like it:

unsigned short foo = 1;
// do something with foo
#if sizeof(short) * CHAR_BIT > 16
   foo &= 0xffff;
#endif

I know this expression can always be fully evaluated at compile time, but maybe it's only evaluated after the preprocessor does it's thing? Is this possible in ANSI C or do I just have to do the check at run time?

Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
Robert S. Barnes
  • 39,711
  • 30
  • 131
  • 179
  • There is no standard way to ask for the size of a data type via the preprocessor. But perhaps you are more interested in the number of significant bits of your data type? Then you shouldn't use `short` at all but follow @larsmans advice and use an appropriate data type. The really correct one would be `int_least16_t` for a type that has at least 16 significant bits. – Jens Gustedt Jul 26 '11 at 12:17

2 Answers2

5

You can't use sizeof in a preprocessor expression. You might want to do something like this instead:

#include <limits.h>

#if SHRT_MAX > 32767
    /* do soemthing */
#endif
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • 1
    +1, even though this is not completely correct, since the OP was asking for the size of the data type and not for its width. In theory, `short` could have a lot of padding bits. Then the original expression would trigger and your expression wouldn't. – Jens Gustedt Jul 26 '11 at 12:12
  • @larsmans: Can't do that, it's ANSI C. int16_t and all the other specific width types are part of C99. – Robert S. Barnes Jul 26 '11 at 17:55
  • @Jens Gustedt: Does the ANSI C standard allow padding bits? What I'm really interested in is how many bits of precision short gives me. I need to work with exactly 16 bits. So I would think the above idea would work fine, although I'd use USHRT_MAX instead. – Robert S. Barnes Jul 26 '11 at 18:05
  • @Robert. By ANSI C I suppose you mean C89? AFAIR C89 was even less restrictive than C99, so it definitively allows for padding bits. If you really need C89, you should somehow test for existance of the int16 types, `#ifdef INT16_MAX` could do this. If it doesn't exist use an approximation through `[U]SHORT_MAX`. Beware, on weird platforms `unsigned short` just mask out the sign bit of `short`. But most platforms should nowadays have `inttypes.h`, better use that if you can. – Jens Gustedt Jul 26 '11 at 19:20
5

If your aim is to stop compilation when a data type is the wrong size, the following technique is useful:

struct _check_type_sizes
{
  int int_is_4_bytes[(sizeof(int) == 4) ? 1 : -1];
  int short_is_2_bytes[(sizeof(short) == 2) ? 1 : -1];
};

(The sizeof() function is interpreted here by the compiler, not the preprocessor.)

The main disadvantage of this method is that the compiler error isn't very obvious. Make sure you write a very clear comment.

Ian Goldby
  • 5,609
  • 1
  • 45
  • 81
  • +1 for creativity. Will this work with the expression `sizeof(short) * CHAR_BIT > 16` ? Just because short is 2 bytes doesn't mean it's 16 bits. ANSI C only guarantees that bytes are at least 8 bits, but they could be more. There are architectures with 9 bit bytes for instance. – Robert S. Barnes Jul 26 '11 at 18:00