这是未定义的行为吗(使用字符串文字)
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 循环时:
迭代次数 - 1:
此处 *(s++)
将存储在 s
中的地址递增 1 并且 returns 未递增的地址(即 s
的 previous/original 值) .所以,没问题,一切正常,打印 Abc
。
迭代次数 - 2:
现在 s
指向一个完全不同的地址(可能有效也可能无效)。现在尝试执行 while(*s)
不是 undefined behavior
吗?
任何帮助将不胜感激!
没有。这里没有未定义的行为。
*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 *s
,s
指向单个字符,递增它会将其调整为指向下一个字符。
#include<stdio.h>
int main()
{
char *s = "Abc";
while(*s)
printf("%c", *s++);
return 0;
}
我已经(在网站上)看到这个代码是正确的,但我觉得这是未定义的行为。
我的推理:
这里s
存放的是字符串文字Abc
的地址。所以在遍历 while 循环时:
迭代次数 - 1:
此处
*(s++)
将存储在s
中的地址递增 1 并且 returns 未递增的地址(即s
的 previous/original 值) .所以,没问题,一切正常,打印Abc
。迭代次数 - 2:
现在
s
指向一个完全不同的地址(可能有效也可能无效)。现在尝试执行while(*s)
不是undefined behavior
吗?
任何帮助将不胜感激!
没有。这里没有未定义的行为。
*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 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.
不,不打印“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 performwhile(*s)
isn't itundefined behavior
?
在迭代 2 中,s
指向“b”。
您可能一直在想一些 char **p
,其中 *p
已设置为指向 "abc"
的指针。在那种情况下,递增 p
会将其更改为指向不同的指针(或指向不受控制的内存),并且会出现问题。事实并非如此;对于 char *s
,s
指向单个字符,递增它会将其调整为指向下一个字符。