这是未定义的行为吗(使用字符串文字)

Is this undefined behaviour ( working with string literal)

#include<stdio.h>

int main()
{ 
   char *s = "Abc";
   
   while(*s)
      printf("%c", *s++);
   
   return 0;
}

我已经(在网站上)看到这个代码是正确的,但我觉得这是未定义的行为。

我的推理:

这里s存放的是字符串文字Abc的地址。所以在遍历 while 循环时:

任何帮助将不胜感激!

没有。这里没有未定义的行为。

*s++ 被评估为 *(s++) 由于后缀增量运算符的 higher precedence 而不是取消引用运算符。所以循环简单地遍历字符串并打印字节并在它看到空字节时停止。

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 ?

没有。在第一次迭代中,s 指向字符 A 处的地址,下一次指向 b ,下一次指向 c 处。当 s 到达字符串末尾的空字节(即 *s 为 0)时,循环终止。

基本上,没有对字符串文字的修改。该循环在功能上等同于:

   while(*s) {
      printf("%c", *s);
      s++;
   }

Now s points to a completely different address

的确,这是一个完全不同但定义明确的地址。 s 引用了字符串文字的下一个字符。所以它只是将 1 添加到指针。

因为字符串文字是 nul(零)终止 while 循环将在 s 引用它时停止。

没有UB

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.

不,不打印“Abc”。 %c 告诉 printf 期待一个字符值并打印它。它打印单个字符,而不是字符串。最初,s 指向 "Abc" 的第一个字符。 s++ 增加它指向下一个字符。

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 ?

在迭代 2 中,s 指向“b”。

您可能一直在想一些 char **p,其中 *p 已设置为指向 "abc" 的指针。在那种情况下,递增 p 会将其更改为指向不同的指针(或指向不受控制的内存),并且会出现问题。事实并非如此;对于 char *ss 指向单个字符,递增它会将其调整为指向下一个字符。