Mohamad-Jaafar NEHME
Mohamad-Jaafar NEHME

Reputation: 1215

uintmax_t not handling 128 bits

I wanted to define gigabyte in my code so I used, firstly, unsigned long. However, unsigned long could not handle 2 * gigabyte.

So, I replaced it with long long but I got the same compilation error/warning: error: integer overflow in expression [-Werror=overflow]

Finally, I looked up for big integers and found that uintmax_t is what I need as it is 128 bits.

Unfortunately, I am still getting the same error. I guess there is a small fault but I could find it.

Please find below the relevant code:

#define kilobyte 1024
#define megabyte 1024 * kilobyte
#define gigabyte 1024 * megabyte
uintmax_t threshold = 2 * gigabyte;

Finally, after running 'make'

g++ -Wall -Wextra -Werror -pedantic -pthread -std=c++0x -g  -o lcr main.cpp

I got:

main.cpp: In function ‘int main(int, char**)’:
main.cpp:104:17: error: integer overflow in expression [-Werror=overflow]
cc1plus: all warnings being treated as errors

Upvotes: 4

Views: 618

Answers (2)

Columbo
Columbo

Reputation: 60999

The product of two ints is clearly still of type int - and the literals we're dealing with in your macros are of type int.
10243 = 230 is just about representable in a 32-bit int. However, 2*230 = 231 is exactly one too large for a 32-bit signed int to hold.

This can be solved by defining the constants as objects of appropriate type:

const std::uintmax_t kilobyte = 1024;
const std::uintmax_t megabyte = 1024 * kilobyte;
const std::uintmax_t gigabyte = 1024 * megabyte;
const std::uintmax_t threshold = 2 * gigabyte;

Thanks to the usual arithmetic conversions being performed on operands of *, no overflow can occur.

Upvotes: 5

Bill Lynch
Bill Lynch

Reputation: 81976

Let's look at a piece of code:

uintmax_t x = 2 * 1024;

What happens here, is we have (int) 2 * (int) 1024, and then we promote the result to uintmax_t.

Instead, we want: (uintmax_t) 2 * (uintmax_t) 1024. We can easily promote the integers to long long via this method:

#define kilobyte 1024ULL
#define megabyte 1024ULL * kilobyte
#define gigabyte 1024ULL * megabyte
uintmax_t threshold = 2ULL * gigabyte;

Upvotes: 2

Related Questions