Products > Programming
C macro to determine if a type is signed
HwAoRrDk:
I need to know at compile-time whether a given type is signed, so I can enable or disable a block of code with an #if.
My first thought - and after some searching around, it turns out also the most common way - was to do the following:
--- Code: ---#define IS_SIGNED_TYPE(type) (((type)-1) < 0)
--- End code ---
But, at least in the scenario I'm attempting to use it in, it doesn't work! :wtf:
As a test, if I do this:
--- Code: ---#if IS_SIGNED_TYPE(uint16_t)
#warning "Type is signed"
#else
#warning "Type is unsigned"
#endif
--- End code ---
My compiler (AVR-GCC) spits out the "Type is signed" message. I'm at a loss to come up with a reason why this fails. What's going wrong here?
ataradov:
This macro is for the code. You are trying to use it in a preprocessor. And all the preprocessor stuff is dome with 'int's and there is no typecasting. The preprocessor also does not know what uint16_t is and it is just being substituted whit 0.
You can replace uint16_t with whatever you want. You still essentially get "(((0)-1) < 0)", which is true in plain integers.
HwAoRrDk:
Ah, I see, thanks. I was starting to suspect it must be something to do with the preprocessor evaluating the expression differently.
Is there any other way of doing such a thing at compile-time?
I can make it a run-time check if I really have to, but ideally I would like to make it compile-time so I can avoid including a whole block of code altogether.
T3sl4co1l:
Remember, macros are just that, macros that are expanded before compilation.
You're actually writing
--- Code: ---#if (((uint16_t)-1) < 0)
--- End code ---
Which doesn't mean very much -- uint16_t isn't a number. Does it not emit a syntax error? Perhaps the preprocessor doesn't emit syntax errors on expressions (should be easy enough to look up, I don't know offhand). I would guess it's evaluating "0 - 1 < 0", which is true for any int type.
Also, it may be evaluating the expression as an int (in which case those are signed zeroes), though again I don't know if the preprocessor uses types or is more basic than that.
This explains a bit more:
https://stackoverflow.com/questions/7469915/value-vs-type-code-to-determine-if-a-variable-is-signed-or-not
Note that something that may seem obvious on familiar machines (e.g., the big-flip version, which assumes twos-complement) need not be supported by the language as such. Notably, C supports ones-complement and other more obscure number systems, more of historical interest but they remain considerations in the standard.
P.S. It occurs to me you may've meant:
--- Code: ---uint16_t var;
...
#if IS_SIGNED_TYPE(var)
...
--- End code ---
which shouldn't result in a syntax error, but it seems just as wrong to test run-time variables at compile-time. Again, I'm not sure what error this would be.
As an expression, evaluated at run time, the function would work fine though. e.g. if(IS_SIGNED_TYPE(var)) { ...}
Tim
HwAoRrDk:
--- Quote from: T3sl4co1l on November 13, 2019, 12:02:27 am ---Which doesn't mean very much -- uint16_t isn't a number. Does it not emit a syntax error?
--- End quote ---
No, it doesn't.
I only got an error when I tried it as "#if IS_SIGNED_TYPE(unsigned int)". I forget right now what the error was - something regarding a right-parenthesis.
Navigation
[0] Message Index
[#] Next page
Go to full version