Products > Programming

C macro to determine if a type is signed

(1/6) > >>

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"
#warning "Type is unsigned"

--- 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?

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.

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.

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:

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;

--- 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)) { ...}



--- 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.


[0] Message Index

[#] Next page

There was an error while thanking
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod