Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
As we all know, the smallest integer is different depending on the compiler, so I have this question: What's the result of (int)-2147483648 divided by (int)-1 you get when you use various compilers? For example, VC6.0, VS2010 etc.?
First let's assume we are in a 32-bit system with two's complement representation where INT_MIN value is the same as -INT_MAX - 1.
This expression:
(int) -2147483648 / (int) -1
is equivalent to
(int) -2147483648 / -1
as -1 is already of type int.
In a 32-bit two's complement system where INT_MAX is 2147483647, the value 2147483648 is of type long1) as it cannot be represented in an int. The value of -2147483648 is also of type long.
The long value -2147483648 can be represented in an int, and the value after the integer conversion of (int) -2147483648 is INT_MIN.
The original expression is then equivalent (under our assumptions) to:
INT_MIN / -1
and this expression is equivalent to INT_MAX + 1 which is not representable in an int. Indeed int type range goes from INT_MIN to INT_MAX. The expression is an integer overflow and integer overflow invokes undefined behavior in C.
(C99, 6.5p5) "If an exceptional condition occurs during the evaluation of an expression (that is, if the result is not mathematically defined or not in the range of representable values for its type), the behavior is undefined."
1) We implicitly assume LONG_MAX is > INT_MAX, otherwise the value 2147483648 is of type long long.
Related
I am trying to understand the meaning of the statement:
(int)(unsigned)-1 == -1;
To my current understanding the following things happen:
-1 is a signed int and is casted to unsigned int. The result of this is that due to wrap-around behavior we get the maximum value that can be represented by the unsigned type.
Next, this unsigned type maximum value that we got in step 1, is now casted to signed int. But note that this maximum value is an unsigned type. So this is out of range of the signed type. And since signed integer overflow is undefined behavior, the program will result in undefined behavior.
My questions are:
Is my above explanation correct? If not, then what is actually happening.
Is this undefined behavior as i suspected or implementation defined behavior.
PS: I know that if it is undefined behavior(as opposed to implementation defined) then we cannot rely on the output of the program. So we cannot say whether we will always get true or false.
Cast to unsigned int wraps around, this part is legal.
Out-of-range cast to int is legal starting from C++20, and was implementation-defined before (but worked correctly in practice anyway). There's no UB here.
The two casts cancel each other out (again, guaranteed in C++20, implementation-defined before, but worked in practice anyway).
Signed overflow is normally UB, yes, but that only applies to overflow caused by a computation. Overflow caused by a conversion is different.
cppreference
If the destination type is signed, the value does not change if the source integer can be represented in the destination type. Otherwise the result is:
(until C++20) implementation-defined
(since C++20) the unique value of the destination type equal to the source value modulo 2n where n is the number of bits used to represent the destination type.
(Note that this is different from signed integer arithmetic overflow, which is undefined).
More specifics on how the conversions work.
Lets's say int and unsigned int occupy N bits.
The values that are representable by both int and unsigned int are unchanged by the conversion. All other values are increased or decreased by 2N to fit into the range.
This conveniently doesn't change the binary representation of the values.
E.g. int -1 corresponds to unsigned int 2N-1 (largest unsigned int value), and both are represented as 11...11 in binary. Similarly, int -2N-1 (smallest int value) corresponds to unsigned int 2N-1 (largest int value + 1).
int: [-2^(n-1)] ... [-1] [0] [1] ... [2^(n-1)-1]
| | | | |
| '---|---|-----------|-----------------------.
| | | | |
'---------------|---|-----------|----------. |
| | | | |
V V V V V
unsigned int: [0] [1] ... [2^(n-1)-1] [2^(n-1)] ... [2^n-1]
Edit: Versions prior to C++ 20 do not require two's complement
It might help understanding the binary representation of -1 which is:
0b1111'1111'1111'1111'1111'1111'1111'1111. I should note, that this is a 4-byte representation of -1. Different machines might represent int differently.
You are casting to unsigned and then back to int which changes how you interpret the 1's and 0's. In decimal (or sometimes called denary), what you're doing is the equivalent of casting it to 4294967295 and then back to -1.
The type of the integer literal is the first type in which the value
can fit, from the list of types which depends on which numeric base
and which integer-suffix was used
Because -1 fits into int, that is how it's interpreted.
See: https://en.cppreference.com/w/cpp/language/integer_literal
this is out of range of the signed type. And since signed integer
overflow
This is not integer overflow. This is binary representation. Integer overflow would be:
int int_max = 2147483647; // this is the maximum integer int on my machine
int one = 1;
int overflow = x + s; // sum is equal to -2147483648
The above is an example integer overflow because the maximum representation
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have tried to access values stored in a vector in reverse order. The following code shows no error:
for (long long int i = 0; i < end.size(); i++)
cout << end[end.size() - 1 - i] << "\n";
But the following code shows runtime error:
for(long long int i = end.size()-1;i>=0;i--) cout<<end[i]<<"\n";
Is there any difference between the two methods?
Is there any difference between the two methods?
end.size() returns std::size_t which is an unsigned type. Given an empty vector, you subtract 1 from unsigned zero. The result is a very large unsigned number due to modular arithmetic that unsigned numbers use.
Here, the behaviour depends on the version of the language, as well as the implementation. If long long can represent the large unsigned value, then you overflow the array with this large index (any index being outside the bounds of an empty vector) and behaviour will be undefined. This would happen on 32 bit systems where std::size_t is presumably 32 bits and long long 64 bits.
If the value is unrepresentable by long long, then prior to C++20, the resulting value will be implementation defined. If that value is negative, then you have desired behaviour, other wise undefined behaviour. After C++20, the result would be congruent with a representable value modulo the number of representable values. If bit width of long long matches with std::size_t, then the result would be -1 and behaviour would be as desired.
In conclusion: Latter approach is broken on some implementations. The first one doesn't have this problem.
The proper way to do it is:
for(auto i=end.size(); i-- ;) cout << end[i] << "\n" ;
Using pow() from the <cmath> library, I get a negative number for some numbers.
2601*((int)pow(10.0,3*2)) = -1693967296
Why is this so? Is due to the fact that int only has a range between -32767 to 32767? Or is it because of the casting?
The behaviour of your program is undefined as you are overflowing a signed integral type.
pow(10.0, 3 * 2) is not returning a negative number. That particular overload will return a double. You are casting that to an int then multiplying that by a constant. That is too big to fit into an int. Did you check INT_MAX (or the equivalent std::numeric_limits<int>::max())on your platform?
It is because of integer overflow.
2601*1000000 > INT_MAX.
Hence overflow.
It's not the pow(), but you preempted the answer.
10 to the 6th power is a million, and a million times 2,601 is
2,601,000,000
For signed integers on your platform, the range is probably
–2,147,483,648 to 2,147,483,647
So you see, you've exceeded that range. The actual overflow difference may seem inconsistent, but that's because of two's complement form.
Yes, It is because of int data type. int range is from -2,147,483,648 to 2,147,483,647, because sizeof(int) is 4 bytes.
To overcome this, you can use unsigned int or long int
Your platform appears to have a 32-bit int. This supports a range of -2147483648 to 2147483647
pow() returns a positive number in a double precision floating point number. This bit works fine.
Your cast converts this to an int, again this is fine.
Where things go wrong is the multiplication. The multiplication overflows, signed overflow is undefined behaviour.
In your case you seem to have ended up with twos complement wraparound but you should be aware that this behaviour is not gauranteed, especially with modern optimising compilers.
How can I portably find out the smallest of INT_MAX and abs(INT_MIN)? (That's the mathematical absolute value of INT_MIN, not a call to the abs function.)
It should be as same as INT_MAX in most systems, but I'm looking for a more portable way.
While the typical value of INT_MIN is -2147483648, and the typical value of INT_MAX is 2147483647, it is not guaranteed by the standard. TL;DR: The value you're searching for is INT_MAX in a conforming implementation. But calculating min(INT_MAX, abs(INT_MIN)) isn't portable.
The possible values of INT_MIN and INT_MAX
INT_MIN and INT_MAX are defined by the Annex E (Implementation limits) 1 (C standard, C++ inherits this stuff):
The contents of the header are given below, in alphabetical
order. The minimum magnitudes shown shall be replaced by
implementation-defined magnitudes with the same sign. The values shall
all be constant expressions suitable for use in #if preprocessing
directives. The components are described further in 5.2.4.2.1.
[...]
#define INT_MAX +32767
#define INT_MIN -32767
[...]
The standard requires the type int to be an integer type that can represent the range [INT_MIN, INT_MAX] (section 5.2.4.2.1.).
Then, 6.2.6.2. (Integer types, again part of the C standard), comes into play and further restricts this to what we know as two's or ones' complement:
For signed integer types, the bits of the object representation shall be divided into three
groups: value bits, padding bits, and the sign bit. There need not be any padding bits;
signed char shall not have any padding bits. There shall be exactly one sign bit.
Each bit that is a value bit shall have the same value as the same bit in the object
representation of the corresponding unsigned type (if there are M value bits in the signed
type and N in the unsigned type, then M ≤ N). If the sign bit is zero, it shall not affect the resulting value. If the sign bit is one, the value shall be modified in one of the
following ways:
— the corresponding value with sign bit 0 is negated (sign and magnitude);
— the sign bit has the value −(2M) (two’s complement);
— the sign bit has the value −(2M − 1) (ones’ complement).
Section 6.2.6.2. is also very important to relate the value representation of the signed integer types with the value representation of its unsigned siblings.
This means, you either get the range [-(2^n - 1), (2^n - 1)] or [-2^n, (2^n - 1)], where n is typically 15 or 31.
Operations on signed integer types
Now for the second thing: Operations on signed integer types, that result in a value that is not within the range [INT_MIN, INT_MAX], the behavior is undefined. This is explicitly mandated in C++ by Paragraph 5/4:
If during the evaluation of an expression, the result is not mathematically defined or not in the range of
representable values for its type, the behavior is undefined.
For C, 6.5/5 offers a very similar passage:
If an exceptional condition occurs during the evaluation of an expression (that is, if the
result is not mathematically defined or not in the range of representable values for its
type), the behavior is undefined.
So what happens if the value of INT_MIN happens to be less than the negative of INT_MAX (e.g. -32768 and 32767 respectively)? Calculating -(INT_MIN) will be undefined, the same as INT_MAX + 1.
So we need to avoid ever calculating a value that may isn't in the range of [INT_MIN, INT_MAX]. Lucky, INT_MAX + INT_MIN is always in that range, as INT_MAX is a strictly positive value and INT_MIN a strictly negative value. Hence INT_MIN < INT_MAX + INT_MIN < INT_MAX.
Now we can check, whether, INT_MAX + INT_MIN is equal to, less than, or greater than 0.
`INT_MAX + INT_MIN` | value of -INT_MIN | value of -INT_MAX
------------------------------------------------------------------
< 0 | undefined | -INT_MAX
= 0 | INT_MAX = -INT_MIN | -INT_MAX = INT_MIN
> 0 | cannot occur according to 6.2.6.2. of the C standard
Hence, to determine the minimum of INT_MAX and -INT_MIN (in the mathematical sense), the following code is sufficient:
if ( INT_MAX + INT_MIN == 0 )
{
return INT_MAX; // or -INT_MIN, it doesn't matter
}
else if ( INT_MAX + INT_MIN < 0 )
{
return INT_MAX; // INT_MAX is smaller, -INT_MIN cannot be represented.
}
else // ( INT_MAX + INT_MIN > 0 )
{
return -INT_MIN; // -INT_MIN is actually smaller than INT_MAX, may not occur in a conforming implementation.
}
Or, to simplify:
return (INT_MAX + INT_MIN <= 0) ? INT_MAX : -INT_MIN;
The values in a ternary operator will only be evaluated if necessary. Hence, -INT_MIN is either left unevaluated (therefore cannot produce UB), or is a well-defined value.
Or, if you want an assertion:
assert(INT_MAX + INT_MIN <= 0);
return INT_MAX;
Or, if you want that at compile time:
static_assert(INT_MAX + INT_MIN <= 0, "non-conforming implementation");
return INT_MAX;
Getting integer operations right (i.e. if correctness matters)
If you're interested in safe integer arithmetic, have a look at my implementation of safe integer operations. If you want to see the patterns (rather than this lengthy text output) on which operations fail and which succeed, choose this demo.
Depending on the architecture, there may be other options to ensure correctness, such as gcc's option -ftrapv.
INT_MAX + INT_MIN < 0 ? INT_MAX : -INT_MIN
Edited to add explanation: Of course the difficulty is that -INT_MIN or abs(INT_MIN) will be undefined if -INT_MIN is too big to fit in an int. So we need some way of checking whether this is the case. The condition INT_MAX + INT_MIN < 0 tests whether -INT_MIN is greater than INT_MAX. If it is, then INT_MAX is the smaller of the two absolute values. If not, then INT_MAX is the larger of the two absolute values, and -INT_MIN is the correct answer.
In C99 and above, INT_MAX.
Quoth the spec:
For signed integer types, the bits of the object representation shall be divided into three
groups: value bits, padding bits, and the sign bit. There need not be any padding bits;
signed char shall not have any padding bits. There shall be exactly one sign bit.
Each bit that is a value bit shall have the same value as the same bit in the object
representation of the corresponding unsigned type (if there are M value bits in the signed
type and N in the unsigned type, then M ≤ N). If the sign bit is zero, it shall not affect
the resulting value. If the sign bit is one, the value shall be modified in one of the
following ways:
the corresponding value with sign bit 0 is negated (sign and magnitude);
the sign bit has the value −(2^M) (two’s complement);
the sign bit has the value −(2^M − 1) (ones’ complement).
(Section 6.2.6.2 of http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)
On most systems, abs (INT_MIN) is not defined. For example, on typical 32 bit machines, INT_MAX = 2^31 - 1, INT_MIN = - 2^31, and abs (INT_MIN) cannot be 2^31.
-INT_MAX is representable as an int in all C and C++ dialects, as far as I know. Therefore:
-INT_MAX <= INT_MIN ? -INT_MIN : INT_MAX
abs(INT_MIN) will invoke undefined behavior. Standard says
7.22.6.1 The abs, labs and llabs functions:
The abs, labs, and llabs functions compute the absolute value of an integer j. If the result cannot be represented, the behavior is undefined.
Try this instead :
Convert INT_MIN to unsignrd int. Since -ve numbers can't be represented as an unsigned int, INT_MAX will be converted to UINT_MAX + 1 + INT_MIN.
#include <stdio.h>
#include <stdlib.h>
unsigned min(unsigned a, unsigned b)
{
return a < b ? a : b;
}
int main(void)
{
printf("%u\n", min(INT_MAX, INT_MIN));
}
I am new to C++, I am confused with C++'s behavior for the code below:
#include <iostream>
void hello(unsigned int x, unsigned int y){
std::cout<<x<<std::endl;
std::cout<<y<<std::endl;
std::cout<<x+y<<std::endl;
}
int main(){
int a = -1;
int b = 3;
hello(a,b);
return 1;
}
The x in the output is a very large integer:4294967295, I know that negative integer convert to unsigned will behave like this. But why x+y in the output is 2?
Contrary to the other answers, there is no undefined behavior here, and there is no overflow. Unsigned integers use modulo 2n arithmetic.
Section 4.7 paragraph 2 of the standard says "If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type)." This dictates that -1 is equal to the largest possible unsigned int (modulo 2n).
Section 3.9.1 paragraph 4 says "Unsigned integers, declared unsigned, shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer." To make it clear what this means, the footnote to this clause says "This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type."
In other words, converting -1 to 4294967295 is not just defined behavior, it is required behavior (assuming 32 bit integers). Similarly, adding 3 to that value and yielding 2 as a result is also required behavior. In this case, the value of n is irrelevant. The third value printed by hello() must be 2 or the implementation is not compliant with the standard.
Because unsigned int's will overflow. In other words, a=-1 (signed) which is 1 value below the maximum value for unsigned int's, 4294967295.
Then you add 3, the int will overflow and start at 0, so -1+3 =2
Passing negative number to unsigned int as parameter gives you an undefined behavior. The default int is a signed. It has a range of –2,147,483,648 to 2,147,483,647. Unsigned int range is from 0 to 4,294,967,295.
This isn't so much having to do with C++ but with how computers represent signed and unsigned numbers.
This is a good source on that. Basically, signed numbers are (usually) represented using two's complement, in which the most significant bit has a value of -2^n. In effect, what his means is that the positive numbers are represented the same in two's complement as they are in regular unsigned binary.
-1 is represented as all ones, which when interpreted as an unsigned integer will be the largest integer that can be represented (4294967295, when dealing with 32 bits).
One of the great things about using two complement to represent signed numbers is that you can perform addition and subtraction in the exact same way as with unsigned numbers and it will work out correctly, so long as the number does not exceed the bounds that can be represented. This isn't as easy with other forms such as signed-magnitude.
So, what this means is that because the result of -1 + 3 = 2, and because 2 is positive, it will be interpreted the same as if it were unsigned. Thus, it prints 2.