Torsten Römer
Torsten Römer

Reputation: 3926

integer overflow in constant expression

While this compiles fine on Linux 64 bit with gcc:

#define CONST_1 255
#define CONST_2 255

#define CONST_PROD ((CONST_1) * (CONST_2))

it gives an overflow warning on avr-gcc (8 bit):

constants.c:13:31: warning: integer overflow in expression [-Woverflow]
 #define CONST_PROD ((CONST_1) * (CONST_2))
                               ^

which is fair enough since the result is too large for a 16 bit signed integer.

The warning goes away when defining the constant(s) like this:

#define CONST_1 255U

or by adding a cast:

#define CONST_PROD ((uint16_t)(CONST_1) * (CONST_2))

I think in effect both do the same but is one way preferred over the other?

Upvotes: 2

Views: 5575

Answers (1)

chux
chux

Reputation: 153338

Avoid casting, which can unexpectedly narrow the value.

Alternatives - best depends on many things. In general, if the number is meant to be unsigned, append a u or use some UINTN_C()

 // u or U the same
 #define CONST_1 255U
 #define CONST_1 255u

 // 1u* to bring about unsigned math.  () around `CONST_1` shouldn't be necessary.
 #define CONST_PROD (1u*CONST_1 * CONST_2)

 // Macros for minimum-width integer constants
 #include <stdint.h>
 // UINT16_C() makes the constant type uint_least16_t
 #define CONST_PROD (UINT16_C(CONST_1) * UINT16_C(CONST_2))

OTOH, if a value is meant to be exact N bits and no other width,

 #define CONST16_MASK_MIDDLE_BITS  ((uint16_t) 0x00FFFF00u)

I see little value with UL. If you want the constant to be a wide type, go for widest.

 #define CONST_1 255ULL
 // or 
 #define CONST_1 ((uintmax_t)255u)

Upvotes: 1

Related Questions