If p is located at 0x1000, then "dcis" will be from 0x1000 to 0x1003, then the NULL terminator will be at 0x1004, and p will point to 0x1005, so it will point PAST the character array. "%s" is located at the next available memory, which would be 0x1005, which is what p now points to, so that's what it printed. I don't know if it's guaranteed to happen that way or if it's undefined behavior, but that's what your program did when I ran it.
It totally depends on how the compiler organizes memory. In gcc the string literal "%s" is stored after the string literal "dcis" in memory, so overrunning the string prints "%s". You can test it like this:
Notice in the read-only section of the file ( .rodata ) the string %s is located directly afterdcis . Since your pointer is just iterating sequentially through memory it naturally hits the next location.
Why would it print "%s" ? You're asking it to print the characters that p points to. Where does p point to? Somewhere off the end of the character array, into memory that isn't yours and that you never set. You never set those characters. They could be anything. They could be "%s". They could be "fnighirw". They could be "don't try to print characters from memory that isn't yours". The program could segFault and crash.
Please tell me that you do understand that your while loop
contains no code, and all you are doing is changing where p points so that it points after the text "dcis". Just so that I can be sure you understand that.
yes, I understand. and I intentionally moving my pointer to the end of the string and checking the behavior.. but why it printed %s in the case of printf ("%s", p); but nothing in the case of printf ("%s\n", p); is my question. If we forget what I am assessing is in my address space or not.
Any how I understand that this behavior is undefined. and if there is any valied reason found (may be specifically in gcc) please share it.
It's clear that in one version, the text %s is right after the dcis.
It's how the gcc compiler builds it. As to why it builds it like that... you'd have to ask the compiler writers, I suppose :) When I open up the hex of the first version, the string %s doesn't appear in it at all, which is interesting.
I think I understand why -- printf("%s\n", s) can be optimized to puts(s).
That said, this is EXACTLY why you shouldn't ever rely on undefined behavior -- because it does weird things you can't predict and is affected by apparently unrelated changes in ways you can't anticipate. Any attempt to make sense of what happens after UB has been invoked is an exercise in futility.