Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
like image 981
Jaafar Avatar asked Oct 28 '25 02:10

Jaafar


1 Answers

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.

like image 150
Columbo Avatar answered Oct 29 '25 16:10

Columbo