We know that sizeof(int) = 4 and 4 > -1 is true so the expected output of the following piece of code is true.
However, it's printing "False". Why is wrong?
#include <stdio.h>
main(){
if (sizeof(int) > -1)
printf("True");
else
printf("False");
}
sizeof returns an unsigned int. -1 cast to an unsigned int ends up being a fairly large number.
sizeof returns size_t type which is of unsigned type. -1 is of signed type and it will be converted to unsigned type implicitly by adding UINT_MAX before comparison .
if(sizeof(int) > -1)
Reason is that sizeof returns (unsigned) value, so -1 was converted to unsigned before comparing.
The Standard says:
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.
Note that if the second operand has a greater rank, the result is different. My compiler gives true for long long:
if (sizeof(int) > -1LL)
Operator sizeof returns a value of some unsigned integral type that has typedef name size_t. For example it can be unsigned long But in any case the rank of size_t is not less than the rank of int.
According to the rules of usual aruthmetic conversions (the C Standard, 6.3.1.8 Usual arithmetic conversions)
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.
So in this expression of the if statement
if (sizeof(int) > -1)
integer constant -1 that has type int is converted to type size_t and has value SIZE_MAX.
SIZE_MAX is greater than 4 (or something else that corresponds to sizeof( int )) returned by the sizeof operator.
Thus the above statement may be rewritten like
if (sizeof(int) > SIZE_MAX)
and it yields false.
Take into account that you could prevent the conversion of the integer constant if its rank would be greater than the rank of size_t.
For example try the following if statement
if (sizeof(int) > -1ll)
in this case if size_t is not defined like unsigned long long then the result of evaluation of the expression will be equal to true as you expected.
Here is a demonstrative program
#include <stdio.h>
int main(void)
{
if ( sizeof( int ) > -1 )
{
puts( "True" );
}
else
{
puts( "False" );
}
if ( sizeof( int ) > -1ll )
{
puts( "True" );
}
else
{
puts( "False" );
}
return 0;
}
Its output is
False
True
Comparing an unsigned integer to a signed integer casts the signed to unsigned, resulting in a garbage value, which happens to be larger than the size of an int.
Now if you were to if ((int)sizeof(int) > -1) that would convert the size of int to a signed integer and produce the expected result when compared to -1.
Related
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.
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.
I have below C code in which I have applied a not operator on a long double variable:
#include <stdio.h>
int main()
{
long double a;
signed char b;
int arr[sizeof(!a+b)];
printf("\n%d",sizeof(arr));
return 0;
}
This code outputs 16. I have problem in understanding what happenes when we apply not operator on long double, as we have done with a.
Please help me to understand whats happeneing with this code.
Thank You!
From the C Standard (6.5.3.3 Unary arithmetic operators)
5 The result of the logical negation operator ! is 0 if the value of
its operand compares unequal to 0, 1 if the value of its operand
compares equal to 0. The result has type int. The expression !E is
equivalent to (0==E).
So in this expression
sizeof(!a+b)
the sub-expression !a has the type int.
There are used the integer promotions of the operand b to the type int in the expression!a + b because the rank of the type signed char is less than the rank of the type int and the type int can represent all values of the type signed char.
From the C Standard (6.3.1.1 Boolean, characters, and integers)
...If an int can represent all values of the original type (as restricted
by the width, for a bit-field), the value is converted to an int;
otherwise, it is converted to an unsigned int. These are called the
integer promotions. 58) All other types are unchanged by the integer
promotions.
So the full expression is equivalent to
sizeof( int )
If the sizeof( int ) is equal to 4 then you have an array declared like
int arr[4];
Its size is equal to 16 that is to 4 * sizeof( int ).
This question already has answers here:
sizeof() operator in if-statement
(5 answers)
Closed 7 years ago.
#include <stdio.h>
main()
{
if (sizeof(int) > -1)
printf("True");
else
printf("False");
}
ANSWER:
False
but according to the logic sizeof(int) return 2 and if(2>-1) return 1 and it should print True.
Why it is behaving otherwise?
First of all, the value produced by sizeof is of size_t which is unsigned type. NOTE
As the unsigned type is of higher rank than the signed type, while performing the comparison, as per the norms of the relation operator, the usual arithmetic conversions are performed, meaning the signed type is promoted to unsigned type.
In your case, the -1, when considered as unsigned, represent the highest possible unsigned value, thus, no wonder
if (sizeof(int) > -1)
Evaluates to false.
Moral of the story: Attempted comparison between a signed and an unsigned is expected to produce weird result, just as in your case. You should enable compiler warning and try to solve the issues reported by the compiler.
NOTE:
From C11, chapter ยง7.19, <stddef.h>,
size_t
which is the unsigned integer type of the result of the sizeof operator.
sizeof is an operator which returns the size and the returned value type is unsigned int.
Since unsigned is having higher rank than singed type, -1 is treated as unsigned number.
-1 in this case is treated as 0xFFFF.
Hence if (sizeof(int) > 0XFFFF) is evaluated to false.
If you write
if ( ( int )sizeof(int) > -1)
you will get the expected result that is True.
Operator sizeof returns a value of type size_t that corresponds to some implementation defined unsigned integer type.
From the C STandard (6.5.3.4 The sizeof and alignof operators)
5 The value of the result of both operators is implementation-defined,
and its type (an unsigned integer type) is size_t, defined in (and other headers).
The rank of size_t in any case greater than or at least equal to the rank of type int. It means that when the compiler need to determine the type of an expression it converts operand will lower rank to the type of the operand with higher rank. If operands have the same rank but one operand has unsigned integer type and other has signed integer type then the common type is unsigned int type.
Thus in the condition of the if statement
if ( sizeof(int) > -1)
-1 is converted to unsigned integer type size_t and due to its internal representation where all bits are set to 1 is freater than the value of sizeof( int )
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.