Not getting expected output for ternary operator - c

Consider the following code in C :
void main() {
char *x = "abc";
char *y = "defgh";
unsigned int c=0;
int len = ((strlen(x) - strlen(y)) > c) ? strlen(x) : strlen(y);
printf("%d\n", len);
}
I'm getting output as 3, but the condition in ternary operator ((strlen(x) - strlen(y)) > c) is false, because this will be 3-5 > 0 which is false. Hence, the output should be 5. I couldn't understand what went wrong.

The strlen function has a return type of size_t which is an unsigned integer type. This means that strlen(x) - strlen(y) also has this type. So instead of resulting in a value of -2 you get a result which is a very large positive value. This value is greater than 0, so the condition is true.
If you cast the results of these functions to int, you'll get the expected result.
int len = (((int)strlen(x) - (int)strlen(y)) > c) ? strlen(x) : strlen(y);

The result of strlen is size_t, which is an unsigned type. Thus the expression:
((strlen(x) - strlen(y)) > c
effectively expands to:
(((size_t)3 - (size_t)5) > 0
And ((size_t)3 - (size_t)5) is not a negative number (there are no negative size_t values). It is instead a very large unsigned value (e.g. 0xFFFFFFFFFFFFFFFE for a 64-bit system), which is in fact larger than 0.

Related

warning: comparison of unsigned expression >= 0 is always true

I have the following error when compiling a C file:
t_memmove.c: In function ‘ft_memmove’:
ft_memmove.c:19: warning: comparison of unsigned expression >= 0 is always true
Here's the full code, via cat ft_memmove.c:
#include "libft.h"
#include <string.h>
void *ft_memmove(void *s1, const void *s2, size_t n)
{
char *s1c;
char *s2c;
size_t i;
if (!s1 || !s2 || !n)
{
return s1;
}
i = 0;
s1c = (char *) s1;
s2c = (char *) s2;
if (s1c > s2c)
{
while (n - i >= 0) // this triggers the error
{
s1c[n - i] = s2c[n - i];
++i;
}
}
else
{
while (i < n)
{
s1c[i] = s2c[i];
++i;
}
}
return s1;
}
I do understand that size_t is unsigned and that both integers will be >= 0 because of that. But since I'm subtracting one from the other, I don't get it. Why does this error come up?
If you subtract two unsigned integers in C, the result will be interpreted as unsigned. It doesn't automatically treat it as signed just because you subtracted. One way to fix that is use n >= i instead of n - i >= 0.
consider this loop:
for(unsigned int i=5;i>=0;i--)
{
}
This loop will be infinite because whenever i becomes -1 it'll be interprated as a very large possitive value as sign bit is absent in unsigned int.
This is the reason a warning is generated here
According to section 6.3.1.8 of the draft C99 standard Usual arithmetic conversions, since they are both of the same type, the result will also be size_t. The section states:
[...]Unless explicitly stated otherwise, the common real type is also the corresponding real type of the result[...]
and later on says:
If both operands have the same type, then no further conversion is needed.
mathematically you can just move the i over to the other side of the expression like so:
n >= i
Arithmetic on unsigned results in an unsigned and that's why you are getting this warning. Better to change n - i >= 0 to n >= i.
Operations with unsigned operands are performed in the domain of unsigned type. Unsigned arithmetic follows the rules of modular arithmetic. This means that the result will never be negative, even if you are subtracting something from something. For example 1u - 5u does not produce -4. If produces UINT_MAX - 3, which is a huge positive value congruent to -4 modulo UINT_MAX + 1.

undefined behaviour of macro in for loop

can anyone explain me the output
I have code like
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
for(d=-1;d <= (TOTAL_ELEMENTS);d++)
{
printf("%d\n",array[d+1]);
}
It shows no output why it is so ?
But when i change the value of d in for loop like d=1 it shows the output why?
if i remove macro TOTAL_ELEMENT wit d<=4 ; i get the desired output why ?
As other stated in their answers, with d = -1 it does not print anything as in:
d <= TOTAL_ELEMENTS
d is converted to an unsigned integer type (TOTAL_ELEMENTS is of type size_t because of sizeof). After conversion d value becomes a huge unsigned integer and the comparison with TOTAL_ELEMENTS value fails.
Then:
printf("%d\n",array[d+1]);
will overflow your array as the last element of your array is at index TOTAL_ELEMENTS - 1 and you access your array up to TOTAL_ELEMENTS + 1.
To display your array elements just use the regular form starting from index 0:
int i;
for (i = 0; i < TOTAL_ELEMENTS; i++)
{
printf("%d\n", array[i]);
}
You need to understand "Conversion rules for comparision between signed and unsigned types". In the example, for(d=-1;d <= (TOTAL_ELEMENTS);d++), here d is signed int, and TOTAL_ELEMENTS is unsigned, and d <= TOTAL_ELEMENTS converts d to unsigned. Unsigned -1 is huge number which is not < TOTAL_ELEMENTS, so the loop never gets executed. Typecast as shown below. It will work.
for(d=-1;d <= (int)(TOTAL_ELEMENTS);d++)
try casting TOTAL_ELEMENTS to int
for(d=-1;d <= (int)(TOTAL_ELEMENTS);d++)

comparison operation [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Unsigned and signed comparison
A riddle (in C)
#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d = -1;
if (d < TOTAL_ELEMENTS)
printf("of course -1 is less than %d",TOTAL_ELEMENTS);
else
printf("how on earth");
return 0;
}
answer is:::Output of the above program is : how on earth
When you perform mixed signed vs. unsigned comparison (where signed type is not larger than unsigned one), the comparison is performed in unsigned domain, i.e. the signed operand is implicitly converted to unsigned type.
In your case TOTAL_ELEMENTS has type size_t, which is unsigned. That means that your d is also implicitly converted to size_t type. So, your d < TOTAL_ELEMENTS is actually interpreted as (size_t) d < TOTAL_ELEMENTS or (size_t) -1 < TOTAL_ELEMENTS.
(size_t) -1 is an extremely large positive value. It is actually the largest possible value of type size_t. Hence the result you get.
In your case you apparently want a signed comparison. For that you have to explicitly convert the unsigned value to signed type (paying close attention not to cause overflow). For example, this will work "as expected"
if (d < (int) TOTAL_ELEMENTS)
...
This is because sizeof_t is mapped to an unsigned long type, so -1 becomes 0xFFFFFFFFFFFFFFFF, a rather large positive integer. Try this:
#include<stdio.h>
#define TOTAL_ELEMENTS(a) ((int)(sizeof((a))/sizeof(*(a))))
int array[] = {23,34,12,17,204,99,16};
int main() {
int d = -1;
if (d < TOTAL_ELEMENTS(array)) {
printf("of course -1 is less than %d",TOTAL_ELEMENTS(array));
} else {
printf("how on earth");
}
return 0;
}
Note how I re-wrote your macro to reference array as its parameter, and added a cast to int to ensure that comparing to -1 would bring an expected result.

c code output unexpected/expected behaviour

what is wrong with this code ? can anyone explain ?
#include <stdio.h>
#include <malloc.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int num;
int d;
int size = TOTAL_ELEMENTS -2;
printf("%d\n",(TOTAL_ELEMENTS-2));
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%d\n",array[d+1]);
return 0;
}
when i print it gives 5, but inside for loop what is happening ?
The sizeof operator returns a value of type size_t, which is an unsigned value. In your for loop condition test:
d <= (TOTAL_ELEMENTS-2)
you are comparing a signed value (d) with an unsigned value (TOTAL_ELEMENTS-2). This is usually a warning condition, and you should turn up the warning level on your compiler so you'll properly get a warning message.
The compiler can only generate code for either a signed or an unsigned comparison, and in this case the comparison is unsigned. The integer value in d is converted to an unsigned value, which on a 2's complement architecture ends up being 0xFFFFFFFF or similar. This is not less than your TOTAL_ELEMENTS-2 value, so the comparison is false.
You're starting the loop by setting d = -1, it should be d = 0. So for the first element you're reading random bits of memory.
If you fix that, then you can change your printf to be
printf("%d\n",array[d]);
As you've also marked this as homework, I'd advise also take a look at your loop terminating condition.

A Macro using sizeof(arrays) is not giving the expected output

#include <stdio.h>
int arr[] = {1, 2,3,4,5};
#define TOT (sizeof(arr)/sizeof(arr[0]))
int main()
{
int d = -1, x = 0;
if(d<= TOT){
x = arr[4];
printf("%d", TOT);
}
printf("%d", TOT);
}
TOT has the value 5 but the if condition is failing..why is that?
Because there are "the usual arithmetic conversions" at work for the if.
The sizeof operator returns an unsigned type ... and d is converted to unsigned making it greater than the number of elements in arr.
Try
#define TOT (int)(sizeof(arr)/sizeof(arr[0]))
or
if(d<= (int)TOT){
That's because sizeof returns an unsigned number, while d is signed. When d implicitly converted to a singed number, and then it is much much larger than TOT.
You should get a warning about comparison of signed-unsigned comparison from the compiler.
Your expression for TOT is an unsigned value because the sizeof() operator always returns unsigned (positive) values.
When you compare the signed variable d with it, d gets automatically converted to a very large unsigned value, and hence becomes larger than TOT.
return type of sizeof is unsigned integer ....that is why if is failing ...because "d" which is treated as signed by the compiler is greater than TOT

Resources