Comparing int64_t and uint64_t [duplicate] - c++

This question already has answers here:
Signed/unsigned comparisons
(6 answers)
Closed 7 years ago.
Does anybody know why this code produces such an output? -1 >= 0!!!
[mahmood#tiger ~]$ cat t.cpp
#include <iostream>
#include <stdint.h>
int main()
{
uint64_t i = 10;
uint64_t j = 10;
int64_t k = -1;
std::cout << "k=" << k << " i-j=" << i-j;
if (k >= i-j)
std::cout << " --> yes k>=i-j\n";
return 0;
}
[mahmood#tiger ~]$ g++ t.cpp
[mahmood#tiger ~]$ ./a.out
k=-1 i-j=0 --> yes k>=i-j
[mahmood#tiger ~]$
I know the types are different and a comparison need two similar types but at the end of the day, it is comparing -1 and 0. Isn't it?

if (k >= i-j)
both sides are converted to unsigned, so perhaps -1 is interpreted as 0xFFFFFFFFFFFFFFFF:
if (0xFFFFFFFFFFFFFFFF >= 0)
According to the standard (emphasis mine):
Expressions [expr]
Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.

No. It's likely comparing 0xffffffffffffffff to 0. The signed variable gets promoted to the unsigned type before the comparison is made. Look up 'arithmetic conversions' in the standard for more details.

Related

Why is the result value of the compare operation different from the mathematically same formula? [duplicate]

This question already has answers here:
c++ vector size. why -1 is greater than zero
(3 answers)
Closed 2 months ago.
I'm having trouble comparing size of a vector and simple constant -1
I believe both of these are logically the same:
(index >= (arr.size() - 1))
((index + 1) >= arr.size())
However, the first one returns 1 not 0.
What's the difference between the two comparisons?
#include <iostream>
#include <vector>
using namespace std;
int main() {
int index = -1;
vector<char> arr(6);
cout << (index >= (arr.size() - 1)) << endl;
cout << ((index + 1) >= arr.size()) << endl;
}
The arr.size method returns an unsigned integer type, so the type of the right-hand side of the comparison is unsigned. This results in the left side being converted to unsigned.
When the value on the left is -1, this gets converted to a very large unsigned number, resulting in the first comparison being true. In the second case, the value on the left is 0 so it doesn't change when being converted to an unsigned type and the comparison is false.
If you compile with -Wall -Wextra it will warn you about a signed / unsigned comparison.
size_t is an unsigned long long.
int is a signed type.
You are trying to compare an unsigned type with a signed one. The size of the vector will never have the value -1.

Why doesn't a negative number modulo a vector size give a negative number? [duplicate]

This question already has an answer here:
C++ size_t modulus operation with negative operand
(1 answer)
Closed 2 years ago.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {1, 2, 3, 4, 5, 6, 7};
int i = -4;
cout << i << endl;
cout << v.size() << endl;
cout << i % v.size() << endl;
cout << -4 % 7 << endl;
}
The above code prints:
-4
7
5
-4
Can someone please explain why i % v.size() prints 5 instead of -4? I'm guessing it has something to do with vector.size(), but unsure what the underlying reasoning is. Thanks in advance.
The operands of % undergo the usual arithmetic conversions to bring them to a common type, before the division is performed. If the operands were int and size_t, then the int is converted to size_t.
If size_t is 32-bit then -4 would become 4294967292 and then the result of the expression is 4294957292 % 7 which is actually 0.
If size_t is 64-bit then -4 would become 18,446,744,073,709,551,612 and the result of this % 7 is 5 which you saw.
So actually we can tell from this output that your system has 64-bit size_t.
In C++ the modulus operator is defined so that the following is true for all integers except for b == 0:
(a/b)*b + a%b == a
So it is forced to be consistent with the integer division, which from C++ 11 onwards truncates to zero even for negative numbers. Hence everything is well defined even for negative numbers.
However, in your case you have an signed / unsigned division (because .size() returns unsigned) and the usual signed/unsigned rules apply. This means that in this case all arguments are converted to unsigned before the operation is carried out (see also Ruslan's comment).
So -4 is converted to unsigned (and becomes a very large number) and then modulo is carried out.
You can also see this as 5 is not a correct answer for -4 modulo 7 with any definition of integer division (3 would be correct).
Arithmetic rules with C and C++ are not intuitive.
Because v.size return size_t.
cout << -4 % size_t(7) << endl; // 5
Take a look modulo-operator-with-negative-values
UPD: and signed-int-modulo-unsigned-int-produces-nonsense-results
This is due to the type of v.size(), which is an unsigned type. Due to integer promotion, this means that the result will also be treated as unsigned, despite i being a signed type.
I am assuming you are compiling on 64 bit. This means that in addition to promotion to unsigned, the result will also be of the 64 bit type unsigned long long. Step by step:
unsigned long long _i = (unsigned long long)-4; // 0xFFFFFFFFFFFFFFFC!
unsigned long long result = _i % (unsigned long long)7; // 5
Since presumably you want to preserve the signedness of i, in this case it is enough to cast v.size() to a signed type to prevent the promotion to unsigned:
i % (int)v.size() will give -4.
From cppreference on Usual arithmetic conversions and C++ standard
Otherwise (the signedness is different): If the unsigned type has conversion rank greater than or equal to the rank of the signed type, then the operand with the signed type is implicitly converted to the unsigned type.
-4 is signed and 7 is size_t which is an unsigned type, so -4 is converted to unsigned first and then modulus is carried out.
With that mind, if you break it down, you will immediately see what is happening:
size_t s = -4; // s = 18446744073709551612 on a 64 bit system
size_t m = 7;
std::cout << s % m << '\n'; //5
The results might be different for a 32-bit system.
cout << -4 % 7 << endl; still prints -4. Why? It's because the type of both -4 and 7 is int.
C++ standard ยง5.13.2.3 Type of an integer literal
The type of an integer-literal is the first type in the list in Table 8 corresponding to its optional integer-suffix in which its value can be represented. An integer-literal is a prvalue.
Table 8: Types of integer-literals without suffix:
int
long int
long long int
So, -4 and 7 both are int in this case and hence the result of modulo is -4.

Why does this stl function call result in an incorrect boolean evaluation? [duplicate]

This question already has answers here:
c++ vector size. why -1 is greater than zero
(3 answers)
Closed 4 years ago.
I was humbly coding away when I ran into a strange situation involving checking the size of a vector. An isolated version of the issue is listed below:
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<std::string> cw = {"org","app","tag"};
int j = -1;
int len = cw.size();
bool a = j>=cw.size();
bool b = j>=len;
std::cout<<"cw.size(): "<<cw.size()<<std::endl;
std::cout<<"len: "<<len<<std::endl;
std::cout<<a<<std::endl;
std::cout<<b<<std::endl;
return 0;
}
Compiling with both g++ and clang++ (with the -std=c++11 flag) and running results in the following output:
cw.size(): 3
len: 3
1
0
why does j >= cw.size() evaluate to true? A little experimenting that any negative value for j results in this weird discrepancy.
The pitfalls here are signed integral conversions that apply when you compare a signed integral value with an unsigned one. In such a case, the signed value will be converted to an unsigned one, and if the value was negative, it will get UINT_MAX - val + 1. So -1 will be converted to a very large number before comparison.
However, when you assign an unsigned value to a signed one, like int len = vec.size(), then the unsigned value will become a signed one, so (unsigned)10 will get (signed)10, for example. And a comparison between two signed ints will not convert any of the both operands and will work as expected.
You can simulate this rather easy:
int main() {
int j = -1;
bool a = j >= (unsigned int)10; // signed >= unsigned; will convert j to unsigned int, yielding 4294967295
bool b = j >= (signed int)10; // signed >= signed; will not convert j
cout << a << endl << b << endl;
unsigned int j_unsigned = j;
cout << "unsigned_j: " << j_unsigned << endl;
}
Output:
1
0
unsigned_j: 4294967295

Why sizeof(int) is not greater than -1? [duplicate]

This question already has answers here:
Comparison operation on unsigned and signed integers
(7 answers)
Closed 8 years ago.
this is my C code :
why is the output "False " ?????
why 4 > -1???
code :
#include <stdio.h>
int main() {
if (sizeof(int) > -1)
printf("True");
else
printf("False");
return 0;
}
Because sizeof(int) is unsigned. So -1 is converted to a large unsigned value.
Because sizeof yields a value of type size_t which is an unsigned type. In > expression usual arithmetic conversions will convert -1 to an unsigned type which is the type of the > result. The resulting value will be a huge positive value.
To get the expected behavior use:
(int) sizeof (int) > -1

C++: max integer [duplicate]

This question already has answers here:
maximum value of int
(7 answers)
Closed 7 years ago.
Is there a C++ cross-platform library that provides me with a portable maximum integer number?
I want to declare:
const int MAX_NUM = /* call some library here */;
I use MSVC 2008 unmanaged.
In the C++ standard library header <limits>, you will find:
std::numeric_limits<int>::max()
Which will tell you the maximum value that can be stored in a variable of type int. numeric_limits is a class template, and you can pass it any of the numeric types to get the maximum value that they can hold.
The numeric_limits class template has a lot of other information about numeric types as well.
See limits.h (C) or climits (C++). In this case you would want the INT_MAX constant.
I know it's an old question but maybe someone can use this solution:
int size = 0; // Fill all bits with zero (0)
size = ~size; // Negate all bits, thus all bits are set to one (1)
So far we have -1 as result 'till size is a signed int.
size = (unsigned int)size >> 1; // Shift the bits of size one position to the right.
As Standard says, bits that are shifted in are 1 if variable is signed and negative and 0 if variable would be unsigned or signed and positive.
As size is signed and negativ we would shift in sign bit which is 1, which is not helping much, so we cast to unsigned int, forcing to shift in 0 instead, setting the sign bit to 0 while letting all other bits remain 1.
cout << size << endl; // Prints out size which is now set to maximum positive value.
We could also use a mask and xor but then we had to know the exact bitsize of the variable. With shifting in bits front, we don't have to know at any time how many bits the int has on machine or compiler nor need we include extra libraries.
I know the answer has been given but I just want to know from my old days, I used to do
int max = (unsigned int)-1
Will it give the same as
std::numeric_limits<int>::max()
?
On Hp UX with aCC compiler:
#include <iostream>
#include <limits>
using namespace std;
int main () {
if (sizeof(int)==sizeof(long)){
cout<<"sizeof int == sizeof long"<<endl;
} else {
cout<<"sizeof int != sizeof long"<<endl;
}
if (numeric_limits<int>::max()==numeric_limits<long>::max()){
cout<<"INT_MAX == lONG_MAX"<<endl;
} else {
cout<<"INT_MAX != LONG_MAX"<<endl;
}
cout << "Maximum value for int: " << numeric_limits<int>::max() << endl;
cout << "Maximum value for long: " << numeric_limits<long>::max() << endl;
return 0;
}
It prints:
sizeof int == sizeof long
INT_MAX != LONG_MAX
I checked both int and long types are 4bytes.
manpage limits(5) says that INT_MAX and LONG_MAX are both 2147483647
http://nixdoc.net/man-pages/HP-UX/man5/limits.5.html
So, conclusion std::numeric_limits< type >:: is not portable.