Rishabh
Rishabh

Reputation: 1

Pointers in ternary operator

When I use a pointer in ternary operator if condition is true it executes exp3

#include <stdio.h>

int main(){

    int a,b;

    printf("Enter first number:");
    scanf("%d",&a);

    printf("Enter second number:");
    scanf("%d",&b);

    printf("Address of a:%u \n",&a);
    printf("Address of b:%u \n",&b);

    int *ptr=&b;

    // when i use pointer in ternary operator if condition is true it execute exp3

   // problem in this line 
   (*ptr++) > (*ptr) ? printf("\n %d is the maximum number",b):printf("\n %d is the maximum number",a);

    (a>b) ? printf("\n %d",a) : printf("\n %d",b);

    return 0;
}

Upvotes: 0

Views: 229

Answers (1)

Adrian Mole
Adrian Mole

Reputation: 51835

There are several issues in your code that cause undefined behaviour (UB). The first is that you are using pointer arithmetic inappropriately. Operations like incrementing, decrementing and comparisons are only really useful on pointers to elements of arrays. In your case, neither a nor b is an array (although, from the compiler's perspective, they can be treated as single-element arrays), so there is no obligation on the compiler to follow any specific relative memory arrangement for those variables: they could be adjacent in memory, or separated by any number of bytes; and, even if they are adjacent, they could be "either way round" (that is, either a or b could be in the lower address).

We can create a 'quick workaround' in your code for this, by declaring an actual array and then make the a and b tokens aliases for elements of that array:

//  int a, b;
    int data[2];
    #define a (data[0])
    #define b (data[1])

Another cause of UB is the use of the wrong printf format specifier when showing your pointers; pointers should be printed using the %p specifier and, even then, should really be cast to void* when passed as arguments to printf:

    printf("Address of a:%p \n", (void*)&a);
    printf("Address of b:%p \n", (void*)&b);

But the third – and perhaps most important – source of UB occurs in the "condition" expression of your conditional ('ternary') operator: the (*ptr++) > (*ptr) comparison.

For this expression, the C Standard does not specify which of the operands of the > is evaluated first (i.e. the > operator is not a sequence point). So, expanding how the compiler might interpret this, using intermediate variables, we could get this:

T1 = (*ptr++);   // T1 will get the value of "a", then "ptr" is incremented
T2 = (*ptr);     // T2 will get the value of "b"
if (T1 > T2) ... // This will now be equivalent to the "a > b" comparison

Alternatively, the compiler would be equally entitled to do this:

T1 = (*ptr);     // T1 will get the value of "a"
T2 = (*ptr++);   // T2 will ALSO get the value of "a" and THEN 'ptr' is incremented
if (T1 > T2) ... // This will now be equivalent to the "a > a" comparison - which is wrong

We can resolve this UB by explicitly using intermediate variables like those above:

    int T1 = *ptr++;
    int T2 = *ptr;
    T1 > T2 ? printf("\n %d is the maximum number", b) : printf("\n %d is the maximum number", a);

But note, even then, your code will show the wrong answer, because of the way the post-increment is applied (that is, after the value of *ptr has been assigned to T1).

If you must use pointers in your code, then avoid the post-increment and just use a simple addition to get the address of b (or the second element) and thus leaving ptr unchanged when using it to refer to a (the first element):

    *(ptr+1) > *ptr ? printf("\n %d is the maximum number", b) : printf("\n %d is the maximum number", a);

Upvotes: 1

Related Questions