Reputation: 1700
#include<stdio.h>
int main()
{
char *s = "Abc";
while(*s)
printf("%c", *s++);
return 0;
}
I have seen this (on a site) as a correct code but I feel this is undefined behavior.
My reasoning:
Here s
stores the address of the string literal Abc
. So while traversing through the while loop :
Iteration - 1:
Here *(s++)
increments the address stored in s
by 1 and returns the non-incremented address (i.e the previous/original value of s
). So, no problem everything works fine and Abc
is printed.
Iteration - 2:
Now s
points to a completely different address (which may be either valid or not). Now when trying to perform while(*s)
isn't it undefined behavior
?
Any help would be really appreciated!
Upvotes: 0
Views: 431
Reputation: 222846
Iteration - 1:
Here
*(s++)
increments the address stored ins
by 1 and returns the non-incremented address (i.e the previous/original value ofs
). So, no problem everything works fine andAbc
is printed.
No, “Abc” is not printed. %c
tells printf
to expect a character value and print that. It prints a single character, not a string. Initially, s
points to the first character of "Abc"
. s++
increments it to point to the next character.
Iteration - 2:
Now
s
points to a completely different address (which may be either valid or not). Now when trying to performwhile(*s)
isn't itundefined behavior
?
In iteration 2, s
is pointing to “b”.
You may have been thinking of some char **p
for which *p
had been set to a pointer to "abc"
. In that case, incrementing p
would change it to point to a different pointer (or to uncontrolled memory), and there would be a problem. That is not the case; for char *s
, s
points to a single character, and incrementing it adjusts it to point to the next character.
Upvotes: 1
Reputation: 67546
Now s points to a completely different address
Indeed, it is a completely different but well defined address. s
referenced the next char of the string literal. So it just adds 1
to the pointer.
Because string literal is nul (zero) terminated the while
loop will stop when s
will reference it.
There is no UB.
Upvotes: 1
Reputation: 121397
No. There's no undefined behaviour here.
*s++
is evaluated as *(s++)
due to higher precedence of postfix increment operator than the dereference operator. So the loop simply iterates over the string and prints the bytes and stop when it sees the null byte.
Now s points to a completely different address (which may be either valid or not). Now when trying to perform while(*s) isn't it undefined behavior ?
No. In the first iteration s
points to the address at the char A
and at b
in the next and at c
in the next. And the loop terminates when s
reaches the null byte at end of the string (i.e. *s
is 0).
Basically, there's no modification of the string literal. The loop is functionally equivalent to:
while(*s) {
printf("%c", *s);
s++;
}
Upvotes: 2