Why does this comparison to sizeof fail? [duplicate] - c

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.

Related

C programming: Division in an if-statement [duplicate]

This question already has answers here:
My computer thinks that signed int is smaller then -1? [duplicate]
(3 answers)
sizeof() operator in if-statement
(5 answers)
Closed 5 years ago.
Why does it print 2 when the value of SIZE is greater than -1?
Link to the code: http://ideone.com/VCdrKy
#include <stdio.h>
int array[] = {1,2,3,4,5,6,7,8};
#define SIZE (sizeof(array)/sizeof(int))
int main(void) {
if(-1<=SIZE) printf("1");
else printf("2");
return 0;
}
Both arguments are in different type
Argument are 'converted' to 'common' type, and 'common' between signed -1 and unsigned SIZE is unsigned.
So -1 is converted -> 0xfffffff (depends on architecture) that is grater than SIZE
From the C standard on integer conversions:
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 is converted to the type of the operand with
unsigned integer type.
Here -1 is of type int, and SIZE is of type size_t. On your c compiler, size_t is unsigned and has greater than or equal rank to int, so the -1 is converted to size_t, which gives a large positive number (SIZE_MAX)

Why x is promoted to unsigned int? [duplicate]

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.

unsigned variable is behaving like signed [duplicate]

This question already has answers here:
Comparison operation on unsigned and signed integers
(7 answers)
In a C expression where unsigned int and signed int are present, which type will be promoted to what type?
(2 answers)
Closed 7 years ago.
This is the code,
#include <stdio.h>
int main()
{
unsigned int i = 0xFFFFFFFF;
if (i == -1)
printf("signed variable\n");
else
printf("unsigned variable\n");
return 0;
}
This is the output,
signed variable
Why is i's value -1 even it is declared as unsigned?
Is it something related to implicit type conversations?
This is the build environment,
Ubuntu 14.04, GCC 4.8.2
The == operator causes its operands to be promoted to a common type according to C's promotion rules. Converting -1 to unsigned yields UINT_MAX.
i's value is 0xFFFFFFFF, which is exactly the same as -1, at least when the later is converted to an unsigned integer. And this is exactly what is happening with the comparison operators:
If both of the operands have arithmetic type, the usual arithmetic conversions are performed. [...]
[N1570 $6.5.9/4]
-1 in two's complement is "all bits set", which is also what 0xFFFFFFFF for an unsigned int (of size 4) is.

Comparison between intN_t and uintN_t [duplicate]

This question already has answers here:
Signed/unsigned comparisons
(6 answers)
Why is a negative int greater than unsigned int? [duplicate]
(6 answers)
Closed 9 years ago.
I'm puzzled. Example:
int x=-1;
unsigned y=0;
(x<y) ----> false
int8_t x=-1;
unint8_t y=0;
(x<y) ----> true
Additionally, the compiler raises warnings on the first comparison, but not the second. It seems that for
(int vs unsigned) - int promoted to unsigned
(intN_t vs uintN_t) - uintN_t promoted to intN_t
Why have this behaviour? Like... really?
Whenever you apply any binary arithmetic operator (including comparisons) to a pair of numeric types which are both shorter than int, C converts both operands to int before performing the operation.
Whenever you apply any binary arithmetic operator to a pair of numeric types which are the same size, mismatched in signedness, and not shorter than int, C converts the signed operand to unsigned before the operation.
These are two of the "integer promotion" rules. They are not terribly intuitive, and they are probably not what one would do if one were designing C from scratch today, but they are what they are and we are stuck with them.
This is a result of the usual integer conversions.
In the first case, both operands have rank at least that of int, and have the same rank, so they are converted to the unsigned integer type.
In the second case, int8_t is char (it has to be, if it exists at all), so both operands are promoted to int. Both -1 and 0 are representable in int, so there is no warning.

Why did these two program behave differently in ANSI C? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
A riddle (in C)
1.
main()
{
if(-1<(unsigned char)1)
printf("-1 is less than (unsigned char)1:ANSI semantics");
else
printf("-1 NOT less than (unsigned char)1:K&R semantics");
}
2.
int array[] = {23,41,12,24,52,11};
#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))
main()
{
int d = -1,x;
if(d<=TOTAL_ELEMENTS -2)
x = array[d+1];
}
The first convert unsigned char 1 to a signed variable in ANSI C,
while the second program convert d to an unsigned int that makes the
condition expression return false in ANSI C.
Why did they behave differently?
For the first one the right-hand side is an unsigned char, and all unsigned char values fit into a signed int, so it is converted to signed int.
For the second one the right-hand side is an unsigned int, so the left-hand side is converted from signed int to unsigned int.
See also this CERT document on integer conversions.
starblue explained the first part of your question. I'll take the second part. Because TOTAL_ELEMENTS is a size_t, which is unsigned, the int is converted to that unsigned type. Your size_t is so that int cannot represent all values of it, so the conversion of the int to size_t happens, instead of the size_t to the int.
Conversion of negative numbers to unsigned is perfectly defined: The value wraps around. If you convert -1 to an unsigned int, it ends up at UINT_MAX. That is true whether or not you use twos' complement to represent negative numbers.
The rationale for C document has more information about that value preserving conversion.
Here's the way I remember how automatic conversions are applied:
if the operand sizes are different, the conversion is applied to the smaller operand to make it the same type as the larger operand (with sign extension if the smaller operand is signed)
if the operands are the same size, but one is signed and the other unsigned, then the signed operand is converted to unsigned
While the above may not be true for all implementations, I believe it is correct for all twos-complement implementations.

Resources