c - 为什么在 strcpy 改变它的值之后 tt[9] 是 '4'?

标签 c

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

Synopsis

    #include <string.h>
    char *strcpy(char * restrict s1,
                 const char * restrict s2);

The strcpy function copies the string pointed to by s2 (including the terminating null character) into the array pointed to by s1. If copying takes place between objects that overlap, the behavior is undefined.

Returns

The strcpy function returns the value of s1.

将包含 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 -Werrorclang -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/

相关文章:

c++ - 为什么当左侧操作数为负值时,左移操作会调用未定义行为?

编译器使用局部变量而不调整 RSP

php - 如何从另一个 php 扩展方法调用 php 扩展方法

c - 不用 Malloc 动态分配内存

C - 在 system() 函数中循环的正确方法是什么?

c - 在c中手动执行,不明白索引-1是什么意思

c - 以下代码片段(C 语言)打印了什么?

凯撒密码输出空行

c - 程序的执行顺序

c - 将子程序链接到主文件时出现问题