This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
A riddle (in C)
see this code
#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;
}
now this loop won't run.
sizeof() would return an unsigned value so TOTAL_ELEMENTS has an unsigned value.
now , coming to the for loop, please tell me if the unary operator '-' works on signed int 2 or an implicit conversion takes place into unsigned and then the '-' operator works.
In your example d is converted to an unsigned int in the comparison. But -1 cannot be represented as an unsigned int value, so it is is converted to UINT_ MAX. To avoid this behaviour you can convert the right side of the comparison to an signed int by prepending (int).
See Understand integer conversion rules for details on integer conversion in C.
There's no unary operator in d <= TOTAL_ELEMENTS-2.
The TOTAL_ELEMENTS-2 reduces to an expression with a binary operator of -. This expression then becomes unsigned because one of its operands is unsigned.
In the case of d <= TOTAL_ELEMENTS-2, d's type is also converted to unsigned int for the same reason.
The relevant portion of the standard is section 6.3.1.8#1 (ISO/IEC 9899:1999) which says:
"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."
Yes, d also has an unsigned type in that expression, because of promotion, which is why the loop fails.
However, the question is whether the C compiler "thinks":
(unsigned) ((unsigned) 5 - (unsigned) 2)
i.e. promoting 2 to unsigned, or:
(unsigned) ((unsigned) 5 - (signed) 2)
i.e. subtraction taking operands of both types. Of course, it doesn't matter, as it would be the same operation for both. However, the whole point is that subtracting will return a value of one type, so theoretically it can only take arguments of that type. So it's the first (unsigned int 2).
P.S. (-2) is unary, while (5 - 2) is binary.
I suspect the unsigned type of sizeof() to propagate to the expression TOTAL_ELEMENTS-2 and then to both operands of d <= TOTAL_ELEMENTS-2. Inserting (int) juste before TOTAL_ELEMENTS fixes the issue.
look , that '-' operator being unary was a stupid thing.forget it.it was the binary '-' , i realise.
when 2 is converted to unsigned int it becomes unsigned 2 , so TOTAL_ELEMENTS-2 has a value equal to unsigned 5 , and then when d is being converted to an unsigned int it gets a large positive value and
so the loop fails.
is that happening here??
and yes, i didn't write this code,this is some c puzzle i found on the web.
thank ya all.
Related
This question already has an answer here:
Applying "not" operator on long double in C
(1 answer)
Closed 2 years ago.
I am trying to understand this code. Can anyone explain why sizeof(!a+b) equals 16? What datatype is returned, after this operation !a+b?
#include <stdio.h>
int main()
{
long double a;
long double b;
int arr[sizeof(!a + b)];
printf("%d", sizeof(arr));
}
The result of !a is integer. Integer + long double = long double.
sizeof(long double) in your implementation is 16.
int is 4 bytes long. sizeof 16 elements integer array is 16 * 4 = 64
!a returns int, per the C11 standard:
Section 6.5.3.3 "Unary arithmetic operators" paragraph 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).
int + long double gives a long double. Again, from the C11 standard:
6.5.6 "Additive operators" paragraph 4
If both operands have arithmetic type, the usual arithmetic conversions are performed on them.
Looking deeper:
6.3.1.8 "Usual arithmetic conversions"
First, if the corresponding real type of either operand is long double, the other operand is converted, without change of type domain, to a type whose corresponding real type is long double.
The extra bits about type domains are in reference to compound types like complex.
In your implementation, sizeof(long double) is 16 (i.e. 128 bits). int is 4 bytes long. Therefore the size of the array is 4 * 16 = 64, which explains the output of your program.
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
This question already has answers here:
Why is −1 > sizeof(int)?
(4 answers)
Closed 6 years ago.
The following program compiles successfully but when i ran it ,it prints nothing when i initialize the for loop with -1 but when i initialize for loop with 0 it successfully traverse all the array.I want to ask that can we don't traverse the array when we initialize the for loop with negative value??
#include <stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23, 34, 12, 17, 204, 99, 16};
int main(void) {
int d;
//printf("%d",TOTAL_ELEMENTS);
for (d = -1; d <= (TOTAL_ELEMENTS - 2); d++)
{
printf("%d ",d);
printf("%d\n", array[d+1]);
}
return 0;
}
The result of sizeof operator is of type size_t, which is an unsigned type.
As a result, the type of TOTAL_ELEMENTS is also unsigned. When -1 is compared with it, it's converted to a big unsigned number. That's why d <= (TOTAL_ELEMENTS - 2) is false.
Here d <= (TOTAL_ELEMENTS - 2) operands are subject of usual arithmetic conversions (6.3.1.8). And actually integer promotions rules act in your case:
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.
According to what you've got your code falls into clause #3, then your signed -1 is converted via rule (6.3.1.3):
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.
As result it becomes a very large unsigned value, that is surely greater than TOTAL_ELEMENTS - 2 and you'll never enter the loop.
This doesn't do what you think it does:
d <= (TOTAL_ELEMENTS - 2)
Instead, do this:
d <= int(TOTAL_ELEMENTS - 2)
Otherwise you've got a signed-vs-unsigned comparison, and your -1 becomes the largest possible size_t.
sizeof produces a result of size_t, which is unsigned. Compare a signed and unsigned type and you can only expect things to blow up.
To elaborate, when you try to use both signed and unsigned type in arithmatic operations, the signed type will be promoted to unsigned type, producing a huge number. Thus, the value of d , promoted to unsigned type, will fail to meet the condition d <= (TOTAL_ELEMENTS - 2);, hence the loop body will not execute.
For operators that expect operands of arithmetic type cause conversions. This pattern is called the usual arithmetic conversions. for this particular case, quoting the standard, chapter §6.3.1.8
Otherwise, the integer promotions are performed on both operands. Then the
following rules are applied to the promoted operands:
[...]
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.
and, regarding the rank,
The rank of any unsigned integer type shall equal the rank of the corresponding
signed integer type, if any.
Also, for reference, quoting C11, chapter 7.19, (emphasis mine)
size_t
which is the unsigned integer type of the result of the sizeof operator;
Hint: Enable compiler warning and it will point to your mistake.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
A riddle (in C)
Can someone please explain what is wrong with this code?
#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;
}
d <= (TOTAL_ELEMENTS-2)
d is signed: it is an int.
But TOTAL_ELEMENTS is unsigned: sizeof yields a size_t value and size_t is an unsigned type.
In the <= expression d is converted to an unsigned number by the way of the usual arithmetic conversions and it becomes a huge number.
When d is -1 and is compared with TOTAL_ELEMENTS-2 (which is size_t type, ie an unsigned integer), d is promoted to a large number in an unsigned type. Then, d is greater than TOTAL_ELEMENTS-2, so the loop is never executed.
c11
§ 6.5.8 Relational operators
If both of the operands have arithmetic type, the usual arithmetic conversions are
performed.
§ 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.
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.