Home > other >  How to express hexadecimal as signed and perform opeartion ? MISRA 10.1
How to express hexadecimal as signed and perform opeartion ? MISRA 10.1

Time:03-01

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 ?

CodePudding user response:

How can I tell that 0xFFFF is signed not unsigned.

You need to know the size of an int on the given system:

  • In case it is 16 bits, then 0xFFFF is of type unsigned int.
  • In case it is 32 bits, then 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.

CodePudding user response:

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;

CodePudding user response:

In C, the default state for most things is signed integer... you have to take steps to make it otherwise

In very simple terms:

#define UNSIGNED_MAGIC_INT  0x7FFFu   // u denotes unsigned
#define   SIGNED_MAGIC_INT  0x7FFF    // no u denotes signed

#define UNSIGNED_MAGIC_LONG 0x7FFFul  // l = long, u denotes unsigned
#define   SIGNED_MAGIC_LONG 0x7FFFl   // l = long, no u denotes signed

etc

Integer promotion may also come into play, depending on use, but that's another subject in its own right.

  • Related