#include <stdio.h>
#include <string.h>
int main(void) {
char tt[20] = "9081726354";
strcpy(tt, tt + 3);
printf("%d\n", strlen(tt) - tt[9] + '5');
return 0;
}
在strcpy
之后,tt
现在是1726354
,它的长度是7
。 '5'
的 ASCII 是 53
。但是在 tt
指向的字符串更改后,我不明白 tt[9]
是 '4'
。
最佳答案
这是 C17 标准的规范:
7.24.2.3 The
strcpy
functionSynopsis
#include <string.h> char *strcpy(char * restrict s1, const char * restrict s2);
The
strcpy
function copies the string pointed to bys2
(including the terminating null character) into the array pointed to bys1
. If copying takes place between objects that overlap, the behavior is undefined.Returns
The
strcpy
function returns the value ofs1
.
将包含 8 个字节的 tt + 3
处的字符串复制到 tt
确实会导致重叠对象之间的复制,因此具有未定义的行为.
然而,由于目标在源之前,复制很可能会按预期进行,tt
的前 8 个字节将被 "1726354"< 覆盖
和一个空字节。偏移量 9
处的字节未更改且仍具有值 '4'
因此您的 printf
语句可能会生成 7 - '4 ' + '5'
,即 8
,但 C 标准不保证此行为。
事实上,当您为转换说明符 %d
传递类型 size_t
的值时,您有另一个未定义行为的实例。 size_t
与 64 位系统上的 int
大小不同,因此类型不匹配也有未定义的行为。您可以通过提高编译器警告级别来检测此类错误:gcc -Wall -Wextra -Werror
或 clang -Weverything -Werror
。
这是一个可靠输出 8
的更正版本:
#include <stdio.h>
#include <string.h>
int main(void) {
char tt[20] = "9081726354";
memmove(tt, tt + 3, strlen(tt + 3) + 1);
printf("%d\n", (int)strlen(tt) - tt[9] + '5');
return 0;
}
请注意,size_t
值可以通过转换说明符 %zu
或 %zd
传递给 printf
但许多遗留系统不支持此 C99 扩展。
关于c - 为什么在 strcpy 改变它的值之后 tt[9] 是 '4'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55989692/