Moe
Moe

Reputation: 17

printing with pointers and strings (C)

can someone explain why this prints out : "d ce" I think i understood why it prints out "d" but i don't understand the "ce"

#include <stdio.h>

int main(void){
    char s1[]="abcd",*cp;

    cp=s1+2;
    printf("%c %s\n",(*(++cp))++,s1+2);

    return 0;
}

Upvotes: 1

Views: 101

Answers (2)

IrAM
IrAM

Reputation: 1738

Hope the inline comments makes it clear.

#include <stdio.h>

int main()
{
    char s1[]="abcd",s2[]="cdef",s3[5],*cp;

    printf("s1 = %p\n", (void*)s1); // prints start address of s1
    
    cp = s1+2; // cp points to 2 chars advanced of s1 i.e 'c'
    
    printf("cp = %p\n", (void*)cp); // prints address at 'c'
    //first increment cp to point to next location, which now points at 'd' from 'c'
    //the outer ++ increments 'd' to 'e' post-fix, so first prints 'd'
    printf("(*(++cp))++ = %c\n", (*(++cp))++); 
                                               
    printf("s1 = %s\n", s1); // you will see "abce"
    printf("s1+2 = %s\n", s1+2); // 2 chars advanced of s1, i.e "ce"
    
    //printf("%c %s\n",(*(++cp))++,s1+2);

    return 0;
}

Upvotes: 0

Lundin
Lundin

Reputation: 213513

TL;DR

In order to understand this code, you need rather in-depth C knowledge of sequence points, undefined behavior and misc "language-lawyer" stuff. If that isn't the case, then just simply forget about writing or understanding artificial crap code like this and you can stop reading here. Advanced explanation follows.


C11 6.5 states:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.

Generally this renders weird code like this undefined behavior. But in this case, 1) s is not a scalar but an aggregate. The scalar is rather the s[3] lvalue. And 2) the )++ increment that changes the value is not unsequenced to another value computation using the object inside the same expression.

(*(++cp))++ and s1+2 are unsequenced in relation to each other but that doesn't matter for the purpose of making a case for undefined behavior.

  • cp=s1+2; here cp is pointing at the 'c'.
  • This expression alone (*(++cp))++ first increases the pointer one step to point at s[3] that contains 'd'. Then it dereferences the pointer so that we get the value 'd'.
  • It then increments the value by 1 with the postfix ++, which on most symbol tables means 'e'.
  • The ++ change of the value is not sequenced in relation to the value computation that happens during s1+2 but it doesn't matter.
  • All arguments are evaluated before the function is called and there is a sequence point after the full evaluation of the argument list.
  • printf then spots %s and de-references the string, a value computation, but sequenced in relation to the previous )++. This prints ce.
  • And finally there is another sequence point before the function returns.

So the code is actually well-defined, even though horribly written.

Upvotes: 2

Related Questions