Why x is promoted to unsigned int? [duplicate] - c

This question already has answers here:
Why is a negative int greater than unsigned int? [duplicate]
(6 answers)
Closed 5 years ago.
Given that code :
int main(void) {
long x = -1;
if (x < sizeof(x)) {
printf("OK\n");
}
else {
printf("Not Ok\n");
}
return 0;
}
Prints:
Not Ok
I have read about usual arithmetic conversions, and from what i understood that if we have a comparison between two operands with different data types, the compiler invokes a data coercion on the operand which is narrower than the other operand, which will convert the the sizeof(x) into unsigned int to match the other operand, any thoughts?
Aside question:
I tried to do casting size(x) as int in the comparison expression as:
if(x < (int) size(x))
It prints Ok, which I find very strange!

You should never compare a signed number to an unsigned number. Add a compiler switch to warn you about this.
Here, in your case, x will be converted to unsigned, -1 becomes SIZE_MAX (the largest number a that std::size_t can hold). It is because sizeof returns an unsigned number (it returns std::size_t, which is unsigned)
The other thing that could happen, but don't happen in practice is that if sizeof(long)>sizeof(std::size_t) then sizeof(x) would be converted to long, so your program would print OK.

Related

Why does this comparison to sizeof fail? [duplicate]

This question already has answers here:
How can (-1 >= sizeof(buffer)) ever be true? Program fail to get right results of comparison
(1 answer)
void main() { if(sizeof(int) > -1) printf("true"); else printf("false"); ; [duplicate]
(3 answers)
sizeof() operator in if-statement
(5 answers)
Why is sizeof(int) less than -1? [duplicate]
(3 answers)
Closed 2 years ago.
#include<stdio.h>
int main()
{
if(sizeof(double) > -1)
printf("M");
else
printf("m");
return 0;
}
Size of double is greater than -1, so why is the output m?
This is because sizeof(double) is of type size_t, which is an implementation-defined unsigned integer type of at least 16 bits. See this for info on sizeof in C. See this for more info on size_t
The -1 gets converted to an unsigned type for the comparison (0xffff...), which will always be bigger than sizeof(double).
To compare to a negative number, you can cast it like this: (int)sizeof(double) > -1. Depending on what your objective is, it may also be better to compare to 0 instead.
Your code has implementation defined behavior: sizeof(double) has type size_t, which is an unsigned type with at least 16 bits.
If this type is smaller than int, for example if size_t has 16 bits and int 32 bits, the comparison would be true because size_t would be promoted to int and the comparison would use signed int arithmetics.
Yet on most current platforms, size_t is either the same as unsigned or even larger than unsigned: the rules for evaluating the expression specify that the type with the lesser rank is converted to the type with the higher rank, which means that int is converted to the type of size_t if it is larger, and the comparison is performed using unsigned arithmetics. Converting -1 to an unsigned type produces the largest value of this type, which is guaranteed to be larger than the size of a double, so the comparison is false on these architectures, which is alas very confusing.
I have never seen an architecture with a size_t type smaller than int, but the C Standard allows it, so your code can behave both ways, depending on the characteristics of the target system.

Why is (-1)%(unsigned int) different than (-1)%(int) +(what is it calculating with uint and is casting to int a good solution) [duplicate]

This question already has answers here:
C : Modulus operator on unsigned int gives unexpected output
(2 answers)
Closed 3 years ago.
#include <stdio.h>
int main()
{
unsigned int a=10;
int b=10;
int c=-1;
printf("%d %d %d",(c%a),(c%(int)a),(c%b));
return 0;
}
Outputs "5 -1 -1" (using https://www.onlinegdb.com/). What is it calculating to arrive at 5? And is just casting the unsigned int to int the correct fix as long as it fits in an int?
All of C's arithmetic operators (except << and >> which only do this with the first operand) promote both operands to a common type before performing the operation, according the the language's rules for type promotion. Promoting c (with value -1) to unsigned performs modular reduction, modulo one plus the max value representable in the type, i.e. one plus UINT_MAX. The -1 cancels out with the "one plus", and the result is UINT_MAX, typically 4294967295. Then 4294967295U % 10U is of course 5.

Why is the unsigned variable storing negative value? [duplicate]

This question already has answers here:
What happens if I assign a negative value to an unsigned variable?
(7 answers)
Assigning negative numbers to an unsigned int?
(14 answers)
Closed 3 years ago.
I have assigned -1 to unsigned int and assuming it would produce an error I compiled the code, much to my astonishment it didn't. I can't understand the reason behind it.
I have tried printing the values to check them manually, but it always shows -1.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main(int argc, char *argv[]) {
unsigned int x = -1;
printf("%u\n", x);
int y = -1;
printf("%d\n", y);
if (x == y) {
printf("\nsame");
} else {
printf("n s");
}
return 0;
}
the expected result would have been an error or a warning
but it compiled as is.
It works because this:
unsigned int x = -1;
causes the int-typed literal -1 to be converted to an unsigned int which is a standard, well-specified, conversion. The draft C11 spec says:
6.3.1.3 Signed and unsigned integers
1 When a value with integer type is converted to another integer type other than
_Bool, if the value can be represented by the new type, it is unchanged.
2 Otherwise, if the new type is unsigned, the value is converted by repeatedly
adding or
subtracting one more than the maximum value that can be represented in the new
type until the value is in the range of the new type.60)
The latter is what is happening here, so assuming 32-bit integers 232 is being added, making the result 0xffffffff.
I don't believe that the printf() with %u prints -1, that would be a rather major bug.
This is allowed by the standard. When you assign -1 to the unsigned type, conceptually at least, the value is converted to a number that can be represented by the repeated addition of 2n where n is the number of bits in that type.
This conversion also happens to the signed type in the comparison x == y (that comparison takes place in unsigned arithmetic since one of the variables is an unsigned type).

why sizeof type compared with integer returns false [duplicate]

This question already has answers here:
sizeof() operator in if-statement
(5 answers)
Why is sizeof(int) less than -1? [duplicate]
(3 answers)
void main() { if(sizeof(int) > -1) printf("true"); else printf("false"); ; [duplicate]
(3 answers)
Why does this if condition fail for comparison of negative and positive integers [duplicate]
(6 answers)
Closed 4 years ago.
one strange behaviour I noticed in below code.
#include<stdio.h>
#include <stdbool.h>
int main()
{
int x = sizeof(int) > -1;
bool z = sizeof(int);
printf("x is %d \t z is %d \n",x,z);
if(sizeof(int)>-1)
{
printf("true\n");
}
else
printf("false\n");
}
Why int x is zero when sizeof(int) > -1 is true and the expected output should be 1.
GCC compiler Warning say's :
prog.c: In function 'main':
prog.c:6:21: warning: comparison of integer expressions of different signedness: 'long unsigned int' and 'int' [-Wsign-compare]
int x = sizeof(int) > -1;
^
prog.c:11:15: warning: comparison of integer expressions of different signedness: 'long unsigned int' and 'int' [-Wsign-compare]
if(sizeof(int)>-1)
So, you are comparing a signed int and an unsigned long int. When -1 is converted to unsigned long int the result is the maximal possible unsigned long int value (same as ULONG_MAX).
C $6.3.1.3, paragraph 2:
Otherwise, if the new type is unsigned, the value is converted by
repeatedly adding or subtracting one more than the maximum value that
can be represented in the new type until the value is in the range of
the new type.
For more information, read cppreference.
The sizeof operator yields not an int but size_t which is an unsigned integer type. When you compare a signed integer like -1 to an unsigned integer you will end up comparing the wrong values.
Do the following changes and the code will work as expected.
#include<stdio.h>
#include <stdbool.h>
int main()
{
int x = (int)sizeof(int) > -1;
bool z = sizeof(int);
printf("x is %d \t z is %d \n",x,z);
if((int)sizeof(int) > -1)
{
printf("true\n");
}
else
printf("false\n");
}
Output:
x is 1 z is 1
true
sizeof operator returns a type of size_t
The size_t type is an unsigned type. usually unsigned int
If you compare an unsigned int with -1 then by the integer promotion rules (Signed to unsigned conversion in C - is it always safe?), both of them will be converted to unsigned.
So -1 will be converted to 65535 and the equation 4>65535 will result in zero.
Difference between signed and unsigned integer types (which includes char) is that negative values are represented by most significant bit set to 1. On most platform the magnitude is represented by binary complement in that case. E.g. for char:
10000001: -(1)0000000 * 01111111 = -127
We should take 00000001, substract 1 from it and invert all bits except sign to get the value.
Now, during comparison signed values treated as unsigned, if other argument is unsigned. There are historical and practical reasons for that, e.g. to avoid ambiguity in character comparison when compiling legacy code. Traditionally all string in C were char* not unsigned char*.
10000001 as unsigned char equals to 129.
So, according to this program -1 is greater than 1.
#include <iostream>
int a = -1;
unsigned int b = 1;
int main(int argc, char** argv)
{
if(b < a) std::cout << "The world is mad.\n";
if(a > b) std::cout << "Yes, it is.\n";
return 0;
}
You always should look out for warning about comparison as well as about "possible data loss". Those are very common source of bug in programs.

Cannot enter in while statement [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Unsigned and signed comparison
unsigned int and signed char comparison
I have a strange behavior when i try to enter in this while statement:
unsigned u = 0;
int i = -2;
while(i < u)
{
// Do something
i++;
}
But it never enters, even if when i set a break point i = -2 and u = 0.
What am I doing wrong? How could i fix this?
It's because the ANSI C standard defines that whenever there is a comparison between a qualified (your unsigned int u) and a non qualified type (your int i), the non qualified type gets promoted to a type of the same type (thus always int), but also inherits the qualifiers of the other quantity (i.e. it becomes unsigned).
When your int, whose value is equal to -2, becames unsigned the first byte undergoes this transformation: 0000 0010 -> 1111 1110. Your int is now a very large positive number, certainly larger of your unsigned int.
There is a solution: cast to signed
while(i < (signed) u)
{
// Do something
i++;
}
By the way, probably your compiler should give you a warning.
You are comparing a signed and unsigned integer and your problems started there...
Don't do that and it should work just fine.

Resources