Example:
int32 Temp;
Temp= (Temp & 0xFFFF);
How can I tell that 0xFFFF
is signed not unsigned. Usually we add a "u" to the hexadecimal number 0xFFFFu
and then perform operation. But what happens when we need a signed result ?
Example:
int32 Temp;
Temp= (Temp & 0xFFFF);
How can I tell that 0xFFFF
is signed not unsigned. Usually we add a "u" to the hexadecimal number 0xFFFFu
and then perform operation. But what happens when we need a signed result ?
How can I tell that 0xFFFF is signed not unsigned.
You need to know the size of an int
on the given system:
0xFFFF
is of type unsigned int
.0xFFFF
is of type (signed) int
.See the table at C17 6.4.4.1 §5 for details. As you can tell, this isn't portable nor reliable, which is why we should always use u
suffix on hex constants. (See Why is 0 < -0x80000000? for an example of a subtle bug caused by this.)
In the rare event where you actually need signed numbers when doing bitwise operations, use explicit casts. For example MISRA-C compliant code for masking out some part of a signed integer would be:
int32_t Temp;
Temp = (int32_t) ((uint32_t)Temp & 0xFFFFu);
The u
makes the 0xFFFFu
"essentially unsigned". We aren't allowed to mix essentially signed and unsigned operands where implicit promotions might be present, hence the cast of Temp
to unsigned type. When everything is done, we have to make an explicit cast back to signed type, because it isn't allowed to implicitly go from unsigned to signed during assignment either.
How to express hexadecimal as signed and perform operation?
When int
is wider than 16 bit, 0xFFFF
is signed and no changes needed.
int32 Temp;
Temp= (Temp & 0xFFFF);
To handle arbitrary int
bit width, use a cast to quiet that warning.
Temp = Temp & (int32)0xFFFF;
Alternatively, use a signed constant as decimal constants, since C99, are always signed.
Temp = Temp & 65535; // 0xFFFF
The alternative idea goes against the "express hexadecimal as signed" but good code avoids naked magic numbers and so the usage of a hex constant is less relevant as the concept of the mask should be carried in its name.
#define IMASK16 65535
...
Temp = Temp & IMASK16;