c语言 - 为什么 strcpy(buffer +i, buffer + i +1) 的工作方式与使用 temporay 数组不同?


#include <stdio.h>
#include <string.h>
int main() {
char buffer[200] = "This is a string";
char buffer1[200];
strcpy(buffer1, buffer);
char vowels[] = "aeiouAEIOU";
int i;
for (i = 0; i < strlen(buffer); i++) {
if (strchr(vowels, buffer[i]) != NULL) {
char tmp[1000];
strcpy(tmp, buffer + i + 1);
strcpy(buffer + i, tmp);

strcpy(buffer1 + i, buffer1 + i + 1);
break;
}
}
printf("buffer=%sn", buffer); // prints "Ths is a string", which is OK
printf("buffer1=%sn", buffer1); // prints "Ths is asstring", which is not OK.
return 0;
}

我正在尝试从字符串中删除一个字符。在下面的代码中,我使用了两种方法来实现这一点,变量bufferbuffer1。但是,其中一个,buffer1,输出一个奇怪的结果。

是什么使得buffer和buffer1包含不同的值?

使用strcpy重叠数组调用未定义的行为。在这种情况下,您应该使用memmove

选自C标准(7.23.2.3 strcpy函数)

  • …如果复制发生在重叠的对象之间,则
  • 这是一个演示程序

    #include <stdio.h>
    #include <string.h>
    int main( void )
    {
    char buffer[200] = "This is a string";
    char vowels[] = "aeiouAEIOU";
    size_t n = strlen( buffer );
    size_t pos = strcspn( buffer, vowels );
    memmove( buffer + pos, buffer + pos + 1, n - pos );
    puts( buffer );
    }
    

    程序输出为

    Ths is a string
    

    请勿重叠

    char *strcpy(char * restrict s1, const char * restrict s2);restrict,它通知调用者不提供指向重叠数据的指针。

    OP的代码使用重叠的数据,因此有未定义的行为(UB)。
    别那样做。


    可以使用memmove()来处理重叠数据。

    size_t sz = strlen(buffer1 + i + 1) + 1;
    memmove(buffer1 + i, buffer1 + i + 1, sz);
    

    最新更新