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;
}
Related
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.
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.
This question already has answers here:
Comparison operation on unsigned and signed integers
(7 answers)
Closed 4 years ago.
int main(void)
{
unsigned int y = 10;
int x = – 4;
if (x > y)
Printf("x is greater");
else
Printf("y is greater");
getch();
return (0);
}
Output: x is greater
I thought the output would be y is greater since it is unsigned. What's the reason behind this?
Because the int value is promoted to an unsigned int. specifically 0xFFFFFFFC on a 32-bit machine, which as an unsigned int is 4294967292, considerably larger than 10
C99 6.3.1.1-p2
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. All other types are unchanged by the integer promotions.
To perform the conversion:
C99 6.3.1.3-p2
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.
Which basically means "add UINT_MAX+1" (as I read it, anyway).
Regarding why the promotion was to the unsigned int side; precedence:
C99 6.3.1.8-p1
...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.
Which tells me int vs. unsigned char should work as expected.
Test
int main()
{
int x = -4;
unsigned int y = 10;
unsigned char z = 10;
if (x > y)
printf("x>y\n");
else
printf("x<y\n");
if (x > z)
printf("x>z\n");
else
printf("x<z\n");
return 0;
}
Output
x>y
x<z
Well look at that.
A comparison between a signed and an unsigned value will be made in "unsigned space". I.e., the signed value will be converted to unsigned by adding UINT_MAX + 1. In implementation using the 2-complement for negative values, no special handling of the values is required under the hood.
In this example, the -4 is turned into a 0x100000000-4 = 0xFFFFFFFC which is clearly > 10.
When you compare two values in C, they both must be of the same type. In this case (int and unsigned int) the int value will be converted to an unsigned int first.
Second, unsigned integer arithmetic in C is done modulo the maximum value of that type + 1 (that is, it "loops around" so UINT_MAX + 1 is 0 again and vice versa). Therefore converting negative values to unsigned results in very large numbers.
The relevant section in the standard says:
6.3.1.3 Signed and unsigned integers
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.
When you compare an int and an unsigned int the int is converted to unsigned int.
The convertion of an int to an unsigned int is done by adding UINT_MAX+1 (note that your int is negative). So actually you are comparing:
if (-3 + UINT_MAX > 10) //Since -4 is converted to UINT_MAX+1-4
Which is true.
The first bit of an int value is used to define if it's a positive or a negative one. (1 = negative, 0 positive)
Your both variable are cast into unsigned int before comparison where the 1 in the first bit will be interpreted as part of your number.
this code should work fine :
int main(void)
{
unsigned int y = 10;
int x = – 4;
if (x > (int) y)
Printf("x is greater");
else
Printf ("y is greater");
getch ( );
return (0);
}
int x=-4 (2's complement of 4 is 1111 1100 =252) and unsigned int y=10 is(0000 1010 =10) so 252 >10 so -4 is greater than 10.
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.
#include<stdio.h>
int main()
{
unsigned int a=6;
int b=-20;
(a+b>6)?puts(">6"):puts("<=6");
return 0;
}
The above code outputs >6. But I got a doubt. b=-20 will hold a negative value (-18)
after doing the 2's complement as it's a signed integer. So it should output <=6 but its
giving an output as >6.
From the C99 standard, section 6.3.1.8 ("Usual arithmetic conversions"):
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.
Basically, in the case of your example code, unsigned int and int have the same rank, so it's equivalent to:
(a + (unsigned int)b > 6)
To fix it, you need to explicitly cast in the other direction, i.e.:
((int)a + b > 6)
The answer is to be found in section "6.3.1.8 Usual arithmetic conversions" of the C99 standard, which favors the unsigned type when a signed type and an unsigned one are passed to a binary operator (the reality is much more subtle than that).
See this blog post for another example of working through the rules in 6.3.1.8.
You are mixing signed and unsigned integers in your code. That is a bad thing. Try the following snippet:
int main()
{
unsigned int a = 0;
int b=-20;
printf("(a + b) = %f", (a + b));
return 0;
}
Don't mix signed and unsigned integers because the compiler will do a silent conversion just when you don't want it to.