【问题标题】:“while(*s++ = *t++)” and malloc“while(*s++ = *t++)” 和 malloc
【发布时间】:2015-06-08 15:16:24
【问题描述】:

当我想要进行手动字符串复制时,我发现以下代码段令人困惑。

int strincmp(char *s1) {
    int l1 = strlen(s1)+1;
    char *s1_copy = malloc(sizeof(char) * l1);
    while(*s1_copy++=*s1++);
    printf("s1_copy = %s , s1 = %s \n",s1_copy,s1);
    return 0;
}

输出令人困惑,因为我希望它输出一个复制的字符串。但具体如下:

s1_copy =  , s1 =

当我替换“while(*s1_copy++=*s1++);”时使用以下幼稚方式声明(将 s1_copy 和 s1 视为数组而不是 ptrs)

int i=0;
while( s1[i] != '\0'){
    s1_copy[i] = s1[i];
    i++;
}   
s1_copy[i] = '\0';

输出是我所期望的。

s1_copy = TenaLynetta , s1 = TenaLynetta

这让我很困惑,为什么第一种方法不起作用。希望这是一个有意义的问题。

【问题讨论】:

  • 复制命令的奇怪名称?
  • 您自己添加了 printf 吗?它显然不会做任何有用的事情,因为指针已经超出了它们各自字符串的末端。将 printf 移出函数或保留原始指针的副本。
  • @envy_intelligence:指针实际上已经(后)递增到每个字符串的终止 \0 之外的一个字符,因此它们都指向未定义的位置 - 然后打印的内容可以是从字面上看任何东西,因为它是未定义的行为。
  • 谢谢你们。这是一种天真的误解。问题是我移动了指针,当我想打印指针时,指针不再位于开始位置。
  • 快捷方式:而不是while(*s1_copy++=*s1++);,使用memcpy(s1_copy, s1, ll);

标签: c string copy malloc


【解决方案1】:

你让你的指针指向分配内存的第一个位置

s1_copy
  |
-----------------------------------
| h   | e   |  l  | l   | o | \0  |
-----------------------------------

在while循环中你不断增加指针,所以在while循环结束时指针实际上指向字符串的结尾而不是字符串的开头。

                                   s1_copy
                                      |
-------------------------------------------
| h   | e   |  l  | l   | o | \0  | ----- |
-------------------------------------------

%s 打印出字符串,直到遇到\0 字符。由于指针指向内存中不受您控制的某个位置,并且您尝试从那里打印字符串,因此它会导致未定义的行为。

原始字符串也以相同的方式修改,但由于未定义的行为,您会看到正确/不正确的输出。

当有未定义的行为时,你永远不知道实际发生了什么

【讨论】:

  • 不同意“没有什么可打印的”。 s1_copys1 一样,也是通过它的空间。 printf("s1_copy = %s\n",s1_copy); 也是 UB。
  • @chux 我的错!我让它听起来像是定义的行为。我想说这两者都会导致未定义的行为。
【解决方案2】:

这是因为指针 s1_copy 和 s1 都递增并到达字符串的末尾(NULL 字符 '\0')。

或者你可以像这样使用它来保持一个指向字符串开头的指针并在末尾打印它。(需要两个额外的指针,所以不太推荐)

int strincmp(char *s1) {
    int l1 = strlen(s1)+1;
    char *s1_dup = s1;
    char *s1_copy = malloc(sizeof(char) * l1);
    char *s1_copy_dup = s1_copy;
    while(*s1_copy++=*s1++);
    s1_copy = s1_copy_dup;
    s1 = s1_dup;
    printf("s1_copy = %s , s1 = %s \n",s1_copy,s1);
    return 0;
}

【讨论】:

    猜你喜欢
    • 2010-10-23
    • 2015-02-26
    • 2015-08-04
    • 2015-12-12
    • 1970-01-01
    • 2012-12-20
    • 2018-05-31
    • 1970-01-01
    • 2010-10-01
    相关资源
    最近更新 更多