Sai
Sai

Reputation: 1700

Is this undefined behaviour ( working with string literal)

#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 :

Any help would be really appreciated!

Upvotes: 0

Views: 431

Answers (3)

Eric Postpischil
Eric Postpischil

Reputation: 222846

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.

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 perform while(*s) isn't it undefined 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

0___________
0___________

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

P.P
P.P

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

Related Questions