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.
Related
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.
This question already has answers here:
Comparison operation on unsigned and signed integers
(7 answers)
Closed 5 years ago.
Here a + b is -14 which should have been lesser than 'a' and hence should have printed NO but it printed yes.
unsigned int a = 6;
int b = -20;
if((a+b) > a){
printf("Yes");
} else {
printf("NO");
}
return 1;
According to the C Standard (6.3.1.8 Usual arithmetic conversions)
1 Many operators that expect operands of arithmetic type cause
conversions and yield result types in a similar way. The purpose is to
determine a common real type for the operands and result. For the
specified operands, each operand is converted, without change of type
domain, to a type whose corresponding real type is the common real
type. Unless explicitly stated otherwise, the common real type is also
the corresponding real type of the result, whose type domain is the
type domain of the operands if they are the same, and complex
otherwise. This pattern is called the 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.
Types unsigned int and int have the same rank.
Thus the value of the variable b from your example is interpreted as an unsigned value.
If to use the correct conversion specifier %u for the expression ( a + b ) in a function call of printf then you might get
#include <stdio.h>
int main(void)
{
unsigned int a = 6;
int b = -20;
printf( "a + b = %u\n", a + b );
return 0;
}
a + b = 4294967282
You compare signed with unsigned. As all values of unsigned cannot be accommodated in the signed so the the signed value is converted to unsigned and is much larger than 6
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.
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.
There is something wrong with the code below... Could someone explain to me whats the problem and why?
#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%d\n",array[d+1]);
return 0;
}
Usual arithmetic conversions.
In the <= expression the int value -1 is converted to the unsigned type of sizeof and becomes a huge value and the <= expression is then false.
Use:
for(d=-1;d <= (int) (TOTAL_ELEMENTS-2);d++)
The sizeof operator:
...
"The value of the result is implementation-defined, and its type (an unsigned integer type)
is size_t, defined in < stddef.h > (and other headers)." - C99 standard.
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." - C99 standard.
The int d(-1) is converted to (TOTAL_ELEMENTS-2) type which is sizeof return type(an unsigned integer). This is usually done by reinterpreting the bits as an unsigned value => -1 signed integer = 0xFFFFFFFF(if int has 32 bits) unsigned integer.
You are trying to compare 0xFFFFFFFF with 0x5(TOTAL_ELEMENTS-2) which is false.
You should have a warning... signed/unsigned mismatch...
C99 standard
Please find the below changes
#include
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d,k;
k=TOTAL_ELEMENTS-2;
for(d=-1;d <=k ;d++)
printf("%d\n",array[d+1]);
return 0;
}