Comparision between a signed/unsigned value with a negative value - c

Program 1:
#include <stdio.h>
int main()
{
if (sizeof(int) > -1)
printf("Yes");
else
printf("No");
return 0;
}
Output : No
Program 2:
#include <stdio.h>
int main()
{
if (2 > -1)
printf("Yes");
else
printf("No");
return 0;
}
Output: Yes
Questions:
What is the difference between program 1 and program 2?
Why sizeof(int) is considered as unsigned?
Why is 2 in program 2 considered as signed?

It is common issue with usual arithmetic conversions between signed and unsigned integers. The sizeof operator returns value of type size_t, that is some implementation-defined unsigned integer type, defined in <stddef.h> (see also this answer).
Integer constant -1 is of type int. When size_t is implemented as "at least" unsigned int (which is very likely to happen in your case), then both operands of binary operator < are converted to unsigned type. Unsigned value cannot be negative, hence -1 is conveted into a large number.

The type of the value returned by the sizeof operator is size_t, which is specified to be an unsigned type (often equivalent to unsigned long).
Simple plain integer literals, like 2 or -1 are always of type int, and int is signed.
If you want an unsigned integer literal, you have to add the U suffix, like 2U.

This is because the sizeof operator returns a value in size_t. This is supposed to be an unsigned type, often implemented as unsigned int.
The number 2 by itself is an int, not unsigned int.

Related

What is the reason behind the "False" output of this code?

This C code gives output "False" and the else block is executing.
The value of sizeof(int) is 4 but the value of sizeof(int) > -1 is 0.
I don't understand what is happening.
#include <stdio.h>
void main()
{
if (sizeof(int) > -1 )
{
printf("True");
}
else
{
printf("False");
}
printf("\n%d", (sizeof(int)) ); //output: 4
printf("\n%d", (sizeof(int) > -1) ); //output: 0
}
Your sizeof(int) > -1 test is comparing two unsigned integers. This is because the sizeof operator returns a size_t value, which is of unsigned type, so the -1 value is converted to its 'equivalent' representation as an unsigned value, which will actually be the largest possible value for an unsigned int.
To fix this, you need to explicitly cast the sizeof value to a (signed) int:
if ((int)sizeof(int) > -1) {
printf("True");
}
The sizeof operator gives a size_t result.
And size_t is an unsigned type while -1 is not.
That leads to problem when converting -1 to the same type as size_t (-1 turns into a very large number, much larger than sizeof(int)).
Since sizeof returns an unsigned value (which by definition can't be negative), a comparison like yours makes no sense. And besides standard C doesn't allow zero-sized objects or types, so even sizof(any_type_or_expression) > 0 will always be true.
You have to be careful when mixing signed and unsigned values in expressions (and sizeof yields a size_t, which is unsigned).
In a fair number of cases (including this one) the compiler will convert both values to the same type before carrying out operations on them--and when you mix signed and unsigned values, that same type will usually be the unsigned type involved. So what happens in this case is that the -1 gets converted to an unsigned--and when converted to an unsigned value, -1 always converts to the largest value that unsigned type can hold.
From there, the rest is probably fairly clear, I'd guess.

if statement selects the wrong condition [duplicate]

This question already has answers here:
why is -1>strlen(t) true in C? [duplicate]
(3 answers)
Closed 2 years ago.
I have a problem with this code: I don't know why it prints B and not A, since the condition is true.
strlen(x) is clearly greater than i. Can you help me?
#include <stdio.h>
#include <string.h>
int main()
{
char x[]="Hello";
int i = -3;
if(strlen(x)>i)
{
printf("A");
}
else
{
printf("B");
}
return 0;
}
The standard function strlen is declared like
size_t strlen(const char *s);
where the type size_t is an implementation defined unsigned integer type the rank of which is not less than the rank of the type int. Usually the type size_t is defined as an alias for the type unsigned long.
In the expression used as a condition of the if statement
if(strlen(x)>i)
the compiler determines the common type of operands using the usual arithmetic conversions. That is the operand i is converted to the type size_t by propagating the sign bit. And as a result the value of the converted operand is a very big unsigned integer of the type size_t that is greater than the returned value of the call of strlen. So the condition evaluates to the logical false.
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
int i = -3;
printf( "( size_t )i = %zu\n", ( size_t )i );
return 0;
}
Its output might look like
( size_t )i = 18446744073709551613
If you want to get the expected by you result in your program you should write
if( ( int )strlen(x)>i)
or for example
if( ( long int )strlen(x)>i)
That is you need to cast the value returned by the function strlen to some signed integer type.
From C17 document, 6.3.1.8, page number 39
Otherwise, if the operand that has unsigned integer type has rank
greater or equal to the rank of the type of the other operand, then
the operand with signed integer type is converted to the type of the
operand with unsigned integer type
size_t strlen(const char *s);
Here, strlen(x) return value of type size_t (unsigned long int). But i is of type int. The rank of size_t is greather than the rank int. So, i will be promoted to size_t.
Unsigend value of -3 is 4294967293 (in my system). And strlen(x) = 5 , so it will print the else statement.
You are trying to compare signed int with unsigned int.
Try
if(signed(strlen(x))>i){}
Or else you may change the value of I to positive int.

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.

Why is (sizeof(int) > -1) false? [duplicate]

This question already has answers here:
Why should be there the involvement of type promotion in this code?
(1 answer)
Comparison operation on unsigned and signed integers
(7 answers)
Closed 7 years ago.
Can You justify the below code:
#include<stdio.h>
int main()
{
if(sizeof(int) > -1)
{
printf("\nTrue\n");
}
else
{
printf("\nFALSE\n");
}
}
The output is FALSE .....suggest me the reason
sizeof(int) has type size_t, which is an unsigned integer type.
-1 has type int, which is a signed integer type.
When comparing a signed integer with an unsigned integer, first the signed integer is converted to unsigned, then the comparison is performed with two unsigned integers.
sizeof(int) > (unsigned int)-1 is false, because (unsigned int)-1 is a very large number on most implementations (equal to UINT_MAX, or the largest number which fits in an unsigned int).
sizeof
yields a value of an unsigned type (namely size_t).
In sizeof(int) > -1 expression, the usual arithmetic conversion applies and -1 is converted to the unsigned type of sizeof which results in a huge unsigned value greater than -1.
It's because the sizeof operator returns an unsigned integer type. When compared with a signed integer type, the signed integer is converted to unsigned. So in effect, you were comparing sizeof(int) against the largest possible unsigned integer.
You can force the size to signed by casting:
#include <stdio.h>
int main()
{
if((int)sizeof(int) > -1)
{
printf("\nTrue\n");
}
else
{
printf("\nFALSE\n");
}
}

C cast and char signedness

So lately, I read on an issue regarding the three distinct types in C, char/unsigned char/signed char. The problem that I now encounter is not something I have experienced up till now (my program works correctly on all tested computers and only targets little-endian (basically all modern desktops and servers using Windows/Linux right?). I frequently reuse a char array I defined for holding a "string" (not a real string of course) as temporary variables. E.g. instead of adding another char to the stack I just reuse one of the members like array[0]. However, I based this tactic on the fact that a char would always be signed, until I read today that it actually depends on the implementation. What will happen if I now have a char and I assign a negative value to it?
char unknownsignedness = -1;
If I wrote
unsigned char A = -1;
I think that the C-style cast will simply reinterpret the bits and the value that A represents as an unsigned type becomes different. Am I right that these C-Style casts are simply reinterpretation of bits? I am now referring to signed <-> unsigned conversions.
So if an implementation has char as unsigned, would my program stop working as intended? Take the last variable, if I now do
if (A == -1)
I am now comparing a unsigned char to a signed char value, so will this simply compare the bits not caring about the signedness or will this return false because obviously A cannot be -1? I am confused what happens in this case. This is also my greatest concern, as I use chars like this frequently.
The following code prints No:
#include <stdio.h>
int
main()
{
unsigned char a;
a = -1;
if(a == -1)
printf("Yes\n");
else
printf("No\n");
return 0;
}
The code a = -1 assigns an implementation-defined value to a; on most machines, a will be 255. The test a == -1 compares an unsigned char to an int, so the usual promotion rules apply; hence, it is interpreted as
`(int)a == -1`
Since a is 255, (int)a is still 255, and the test yields false.
unsigned char a = -1;
ISO/IEC 9899:1999 says in 6.3.1.3/2:
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
We add (UCHAR_MAX+1) to -1 once, and the result is UCHAR_MAX, which is obviously in range for unsigned char.
if (a == -1)
There's a long passage in 6.3.1.8/1:
If both operands have the same type, then no further conversion is needed.
Otherwise, if both operands have signed integer types or both have unsigned
integer types, the operand with the type of lesser integer conversion rank is
converted to the type of the operand with greater rank.
Otherwise, if the operand that has unsigned integer type has rank greater or
equal to the rank of the type of the other operand, then the operand with
signed integer type is converted to the type of the operand with unsigned
integer type.
Otherwise, if the type of the operand with signed integer type can represent
all of the values of the type of the operand with unsigned integer type, then
the operand with unsigned integer type is converted to the type of the
operand with signed integer type.
Otherwise, both operands are converted to the unsigned integer type
corresponding to the type of the operand with signed integer type.
The rank of unsigned char is less than that of int.
If int can represent all the values that unsigned char can (which is usually the case), then both operands are converted to int, and the comparison returns false.
If int cannot represent all values in unsigned char, which can happen on rare machines with sizeof(int)==sizeof(char), then both are converted to unsigned int, -1 gets converted to UINT_MAX which happens to be the same as UCHAR_MAX, and the comparison returns true.
unsigned char A = -1;
results in 255. There is no reinterpretation upon assignment or initialization. A -1 is just a bunch of 1 bits in two's complement notation and 8 of them are copied verbatim.
Comparisons are a bit different, as the literal -1 is of int type.
if (A == -1)
will do a promotion (implicit cast) (int)A before comparison, so you end up comparing 255 with -1. Not equal.
And yes, you have to be careful with plain char.
I think this question is best answered by a quick example (warning: C++, but see explanation for my reasoning):
char c = -1;
unsigned char u = -1;
signed char s = -1;
if (c == u)
printf("c == u\n");
if (s == u)
printf("s == u\n");
if (s == c)
printf("s == c\n");
if (static_cast<unsigned char>(s) == u)
printf("(unsigned char)s == u\n");
if (c == static_cast<char>(u))
printf("c == (char)u\n");
The output:
s == c
(unsigned char)s == u
c == (char)u
C is treating the values differently when used as-is, but you are correct in that casting will just reinterpret the bits. I used a C++ static_cast here instead to show that the compiler is okay with doing this casting. In C, you would just cast by prefixing the type in parenthesis. There is no compiler checking to ensure that the cast is safe in C.

Resources