-4
int main(){
   char* str="Hello";
     // str: 0x4006db, *str++: l, str: 0x4006db, *str++: e, str: 0x4006db, *str++: H
     printf("str: %p, *str++: %c, str: %p, *str++: %c, str: %p, *str++: %c\n", str, *str++, str, *str++, str, *str++);
}

I hope this is not another stupid question:

  1. Why the value of the str pointer has not changed after I incremented it by *str++?

  2. If the str pointer value hasn't changed, every time I do a *str++ I should yield the same value, and not, l e H.

  3. Why is the letter l appear first and not the H?

Btw, I also looked at the value of &str, it is the same before and after I did the *str++.

Any help will be much appreciated. Thanks

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
Chloe
  • 47
  • 5
  • 1
    You have undefined behavior. – Spikatrix Mar 21 '16 at 11:55
  • 1
    In `str++` the ++ is a POST-increment. So it passes `*str` to printf and only then increments `str` (it will now point to the next character). And the parameters are evaluated right-to-left. – Paul Ogilvie Mar 21 '16 at 11:56
  • 1
    'I hope this is not another stupid question' - well, unfortunately.... – Martin James Mar 21 '16 at 12:19
  • 2
    Please tell your prof/TA to STOP issuing such assignments, and to stay off the tequila when dreaming them up. – Martin James Mar 21 '16 at 12:23
  • 1
    This is not a bad question but enough research for similar questions is clearly not done. – sjsam Mar 21 '16 at 12:41
  • @PaulOgilvie how come the value of str has not changed after its 1st increment? – Chloe Mar 21 '16 at 12:55
  • @CoolGuy care to elaborate which part?? Both deferencing a string pointer and incrementing a pointer seems legal to me. Note that I am not trying to modify the string at all, just simply reading it. – Chloe Mar 21 '16 at 15:13
  • @MartinJames this is not a assignment or homework of any kind, just sth I stumbled upon while familiarising myself with the language. – Chloe Mar 21 '16 at 15:16
  • @Chloe Using `++` without a sequence point in between. For the same reason why stuff like [`int i = 0; printf("%d %d\n", i++, i++);` is UB](http://stackoverflow.com/a/21220630/3049655). – Spikatrix Mar 21 '16 at 15:17
  • @CoolGuy thanks heaps. – Chloe Mar 21 '16 at 15:28

3 Answers3

2

You invoked undefined behaviour by:

  1. Modifying a string literal.
  2. Printing a pointer without casting it to (void *).
  3. Modifying a same object multi-times between two sequence points.

Also note that the order of evaluation of the arguments to a function call is unspecified.

Invoking one undefined behaviour is fatal, which means everything from it working properly as you want to destroying the world can happen, and you invoked three :(

See also:

http://www.c-faq.com/expr/evalorder2.html

http://www.c-faq.com/expr/comma.html

nalzok
  • 14,965
  • 21
  • 72
  • 139
1

The C99 standard says in 6.5.2.2, 10:

The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

Indeed, looking at the assembler my VC2008 produced, the effect of the ++ was only visible just before the function call. During evaluation of the arguments, it used the original str and placed the ++ in a temporary variable. As the order of evaluation is unspecified, the compiler could also have used another strategy.

For example, as I have observed (and used) in older compilers, the arguments are evaluated right-to-left and pushed onto the stack right-to-left and all intermediate operations were visible in the arguments to the left.

However, as there is a sequence point before the function call, all the ++ operations were suddenly visible in str before the function call.

Nice example of Undefined Behavior (UB).

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
0

Here is some code that if you study and compile / run it will help you understand what is going on. Note when the value of pointer ptr_ucW0 is incremented.

/*
 *  36130330_main.c
 */
#include <stdio.h>
#include <string.h>

unsigned int main
    (
    unsigned int    argc,
    unsigned char   *arg[]
    )
{
    unsigned char   *str="Hello";
    unsigned char   *ptr_ucW0;

    printf("\n");
    printf("  Set ptr_ucW0 = str\n");
    ptr_ucW0 = str;
    printf("  Text            Address      Text                Value\n");
    printf("  str       :     %p     *str         :      %c\n", str, *str);
    printf("  str + 1   :     %p     *(str + 1)   :      %c\n", str + 1, *(str + 1));
    printf("  str + 2   :     %p     *(str + 2)   :      %c\n", str + 2, *(str + 2));
    printf("  str + 3   :     %p     *(str + 3)   :      %c\n", str + 3, *(str + 3));
    printf("  str + 4   :     %p     *(str + 4)   :      %c\n", str + 4, *(str + 4));
    printf("  str + 5   :     %p     *(str + 5)   :      %c\n", str + 5, *(str + 5));
    printf("  ptr_ucW0  :     %p     *ptr_ucW0    :      %c\n", ptr_ucW0, *ptr_ucW0);
    printf("  ptr_ucW0++:     %p     *ptr_ucW0++  :      %c\n", ptr_ucW0++, *ptr_ucW0++);
    printf("  ptr_ucW0  :     %p     *ptr_ucW0    :      %c\n", ptr_ucW0, *ptr_ucW0);
    printf("  ptr_ucW0++:     %p     *ptr_ucW0++  :      %c\n", ptr_ucW0++, *ptr_ucW0++);
    printf("  ptr_ucW0  :     %p     *ptr_ucW0    :      %c\n", ptr_ucW0, *ptr_ucW0);
    printf("\n");
    printf("  Reset ptr_ucW0 = str\n");
    ptr_ucW0 = str;
    printf("  Text            Address      Text                Value\n");
    printf("  ptr_ucW0  :     %p     *ptr_ucW0    :      %c\n", ptr_ucW0, *ptr_ucW0);
    printf("  ptr_ucW0++:     %p     *ptr_ucW0    :      %c\n", ptr_ucW0++, *ptr_ucW0);
    printf("  ptr_ucW0++:     %p     *ptr_ucW0    :      %c\n", ptr_ucW0++, *ptr_ucW0);
    printf("  ptr_ucW0++:     %p     *ptr_ucW0    :      %c\n", ptr_ucW0++, *ptr_ucW0);
    printf("  ptr_ucW0++:     %p     *ptr_ucW0    :      %c\n", ptr_ucW0++, *ptr_ucW0);
    printf("  ptr_ucW0++:     %p     *ptr_ucW0    :      %c\n", ptr_ucW0++, *ptr_ucW0);
}
SkyPirate
  • 35
  • 6
  • One more thing, you really should not mess with the base address of the string, in this case str. Doing so will only lead to bad things happening. – SkyPirate Mar 21 '16 at 12:59