为什么 C 中的字符串在 realloc 中为 +1?如果它是针对 null 终止符的,那么如果末尾没有 null 字节,strlen() 如何测量 str 的 len?[复制]

Why +1 in realloc for string in C? If it's for null terminator, then how does strlen() measures len of the str if there's no null byte at the end? [duplicate]

提问人:Prabash 提问时间:10/25/2023 最后编辑:Ulrich EckhardtPrabash 更新时间:10/25/2023 访问量:77

问:

此代码来自 HackerRank 中的一个问题(问:在 C 中打印令牌)。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    char *s = malloc(1024 * sizeof(char));  // Allocate for string
    scanf("%[^\n]", s);
    s = realloc(s, strlen(s)+1);   // Here's my doubt

    // Solution
    
    return 0;
}

忘掉这个问题,看看下面的迭代——

s = realloc( s, strlen(s)+1 );   // +1

这行代码根据字符串 's' 的长度重新分配字符串 's' 的内存,它还增加了 null 终止符 '\0' 的长度。但是 strlen() 只测量直到它达到 '\0',但 's' 中没有 '\0',因为我们要为 '\0' 添加一个字节。我们怎么能假设它会测量字符串“s”的完美长度?如果它测量的是“s”的完美长度,那么末尾必须有一个空终止符,那么为什么要再加 1 呢?

有人解释这一点,没有空终止符“\0”,所以我们为它添加一个字节。

还是我完全错了?

c 内存 realloc strlen

评论

1赞 Pepijn Kramer 10/25/2023
您的问题与 C++ 有什么关系?你的代码显然是C,而C++是一种不同的语言。选择一个。在 C++ 中,我们不会打扰所有手动内存管理并使用 std::string(完全不同的答案)
1赞 Gerhardh 10/25/2023
当然,字符串中有一个 nul-terminator。 把它放在最后一个输入字符之后。否则它根本不是 C 中的字符串。该调用只能用于减小缓冲区的大小。它不能以这种方式增加它。scanfrealloc
1赞 Some programmer dude 10/25/2023
如果没有 null 终止符,则它不是以 null 结尾的字符串。并且您不能将其传递给任何需要以 null 结尾的字符串的函数。所有这些函数都将越界并具有未定义的行为
0赞 Lundin 10/25/2023
与您的问题无关,就执行速度而言,这是一些非常糟糕的代码。没有 realloc 会更好。
0赞 Fe2O3 10/26/2023
OT:为什么 HackerRank 入门代码用于此文本处理挑战?#include <math.h>

答:

2赞 Gerhardh 10/25/2023 #1

有人解释这一点,没有空终止符“\0”,所以我们为它添加一个字节。

你误解了这里发生的事情。

scanf用于将字符串读入 所指向的内存中。 在 C 语言中,字符串是以 nul 结尾的字符序列。这意味着,它负责将 0 字节放在输入的最后一个字符之后。sscanf

如果不是这种情况,则根本不允许您传递,因为它需要以 nul 结尾的字符串。sstrlen

在 is not add 中添加一个 0 字节。添加它是为了保留该字节的内存。从较大的缓冲区开始,然后调整为所需的长度。为此,必须添加 1 以防止在 期间释放最后一个字节。realloc+1realloc

因此,假设不会有 nul 终止符是错误的。它一直存在,并且在减小缓冲区大小后仍将存在。