Malloc,为字符串动态分配错误大小的内存

s5a0g9ez  于 2022-12-17  发布在  其他
关注(0)|答案(3)|浏览(113)
int main() {
    char A[200], B[200];
    printf("Enter 2 words or sentences.\n");
    gets(A);
    gets(B);
    char* C = (char*)malloc((strlen(A) + strlen(B)) * sizeof(char));
    for (int i = 0; i < strlen(A); i++)
        C[i] = A[i];
    for (int i = 0; i < strlen(B); i++)
        C[i + strlen(A)] = B[i];
    printf("%s", C);
}

C的初始值是ÍÍÍÍÍÍÍÍÍÍýýýý,比请求的长4个符号,并且在打印C时这4个符号也显示为输出。我不知道为什么会有4个符号,这就是为什么我在这里寻求解释。

vxqlmq5t

vxqlmq5t1#

问题:

非 * 空字符 * 终止

代码尝试printf("%s", C);,这是 * 未定义的行为 *,因为C[]不是"%s"所需的 * 字符串 *。

// Append a \0
C[strlen(A) + strlen(B)] = '\0';

分配的内存不足

为 * 空字符 * 腾出空间。

// (strlen(A) + strlen(B)) * sizeof(char)
strlen(A) + strlen(B) + 1

自C11以来,gets()不再是标准C库的一部分

使用fgets()并删除可能的尾随'\n'以获得类似的行为。

intsize_t的比较

int不足以处理非常长的字符串。size_t适用于所有字符串。

避免可能重新计算字符串长度

int main(void) {
    char A[200], B[200];
    printf("Enter 2 words or sentences.\n");

    // Code should check the return value of fgets()
    // Omitted for brevity.
    fgets(A, sizeof A, stdin);

    A[strcspn(A, "\n")] = '\0'; // Lop off potential \n
    fgets(B, sizeof B, stdin);
    B[strcspn(B, "\n")] = '\0';

    size_t A_len = strlen(A);
    size_t B_len = strlen(B);
    char* C = malloc(A_len + B_len + 1);

    if (C) {
      for (size_t i = 0; A[i]; i++) {
        C[i] = A[i];
      }
      for (size_t i = 0; B[i]; i++) {
        C[A_len + i] = B[i];
      }
      C[A_len + B_len + i] = '\0';

      printf("%s\n", C);
      free(C);  // Good housekeeping to free allocations.
    }
}
b09cbbtk

b09cbbtk2#

malloc只返回一个指针,指向它分配给你的内存,它不会初始化内存,或者清零,或者类似的操作,所以当你打印出来的时候,你看到的是之前的垃圾。
坦白地说,你很幸运没有打开一个虫洞或其他什么东西,C字符串是空终结的,所以当你传递指针时,从技术上讲你还没有传递字符串,当你把它传递给一个期望字符串的函数时,各种各样的古怪行为都会随之而来。
您应该在获得内存时对其进行初始化。最简单的初始化是类似于*C = '\0';C[0] = '\0';,这会将内存转换为零长度字符串。但是您可能已经有一些内容要放在那里了,或者您一开始为什么要分配内存?:P
现在有了代码,我们可以稍微调整一下来解决这个问题...

int main() {
    char A[200], B[200];
    printf("Enter 2 words or sentences.\n");

    // BTW: you should never, ever be using `gets`.
    // use `fgets` and pass the size of your buffer to avoid overruns.
    // note: it returns a null pointer if it fails...at which point you
    // can't trust that A and B are strings, and should probably bail
    if (!fgets(A, sizeof A, stdin)) return 1;
    if (!fgets(B, sizeof B, stdin)) return 1;

    // you don't want to call `strlen` over and over. save these lengths
    size_t Alen = strlen(A);
    size_t Blen = strlen(B);

    // lop off the newlines
    if (Alen && A[Alen - 1] == '\n') A[--Alen] = '\0';
    if (Blen && B[Blen - 1] == '\n') B[--Blen] = '\0';

    // You need enough space for both strings, plus a nul at the end.
    // side note: you don't need to cast the pointer to a `char *`.
    // also, sizeof(char) is 1 by definition, so no need to multiply by it.
    char* C = malloc(Alen + Blen + 1);
    if (!C) return 1;

    // compare to the length variable instead
    for (int i = 0; i < Alen; i++)
        C[i] = A[i];
    
    for (int i = 0; i < Blen; i++)
        C[i + Alen] = B[i];

    // important: nul-terminate the string
    C[Alen + Blen] = '\0';

    printf("%s", C);

    // not strictly necessary at the end of main on a modern OS, but
    // you should free what you malloc
    free(C);
}
emeijp43

emeijp433#

C[strlen(A) + strlen(B)] = '\0';malloc摆脱了垃圾之后,感谢大家的想法。

相关问题