Reputation: 1215
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
Reputation: 60999
The product of two int
s 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
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