Daniel Jørgensen
Daniel Jørgensen

Reputation: 1202

#define returns a wrong number in C

I'm trying to this very basic task in C, where I want to define a number of ints in a header file. I've done this like so:

#define MINUTE (60)
#define HOUR   (60 * MINUTE)
#define DAY    (24 * HOUR)

The problem is that while MINUTE and HOUR return the correct answer, DAY returns something weird.

Serial.println(MINUTE); // 60
Serial.println(HOUR); // 3600
Serial.println(DAY); // 20864

Can someone explain why this happens?

Upvotes: 1

Views: 166

Answers (3)

too honest for this site
too honest for this site

Reputation: 12263

Assuming you have something like

int days = DAY;

or

unsigned days = DAY;

You seem to have 16 bit integers. The max. representable positive value for (signed) 2s complement integers with 16 bits is 32767, for unsigned it is 65535.

So , as 24 * 3600 == 86400, you invoke undefined behaviour for the signed int and wrap for the unsigned (the int will likely wrap, too, but that is not guaranteed).

This results in 86400 modulo 65356 (which is 2 to the power of 16) which happens to be 20864.

Solution: use stdint.h types: uint32_t or int32_t to get defined sized integers.

Edit: Using function arguments follows basically the same principle as the initialisers above.

Update: As you clamed, when directly passing the integr constant 86400 to the function, this will have type long, because the compiler will automatically choose the smallest type which can hold the values. It is very likely that the println methods are overloaded for long arguments, so they will print the correct value.

However, for the expression the original types are relevant. And all values 24, 60, 60 will have int type, so the result will also be int. The compiler will not use a larger type, just because the result might overflow. Use 24L and you will get a long result for the macros, too.

Upvotes: 4

ash
ash

Reputation: 5165

20864 = 86400 % 65536

Try storing the value in an int instead of a short.

Upvotes: 0

gnasher729
gnasher729

Reputation: 52622

It looks like you actually managed to dig up an ancient 16 bit compiler (where did you find it? ) Otherwise I'd like to see the code that produces these numbers.

Upvotes: 4

Related Questions