c-realloc如何处理字符串中的空字节



这里的C程序员相对较新。我正在复习下面的代码,作为我正在练习C的一个附带项目的教程。abuf结构的要点是创建一个可以附加到的字符串

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct abuf {
char* str;
unsigned int size;
} abuf;

void abAppend(abuf *ab, const char *s, int len) {
char *new = realloc(ab->str, ab->size + len);
if (new == NULL) return;
memcpy(&new[ab->size], s, len);
ab->str = new;
ab->size += len;
}
int main(void) {
abuf ab = {
NULL,
0
};
char *s = "Hello";
abAppend(&ab, s, 5);
abAppend(&ab, ", world", 7);
return 0;
}

所有的编译和我的测试(为了简单起见进行了编辑)都表明;你好"存储在ab的str指针中;你好,世界"在对CCD_ 3的第二次调用之后。然而,这段代码让我感到困惑。在对abAppend的初始调用中,str指针为null,因此根据其手册页,realloc应该表现得像malloc,并分配5字节的空间来存储字符串。但是字符串";你好"还包含终止的空字节\0。如果我理解正确的话,这应该是字符串的第六个也是最后一个字节。如果我们存储"0",这个空字节不是丢失了吗;你好\0"在CCD_ 8的容器中;你好"?

在对abAppend的第二次调用中;,世界;至CCD_ 10。realloc将把str放大到12个字节,但不考虑第13个字节\0。然而,一切都正常,如果我用for (int i = 0; ab.str[i] != ''; i++)这样的循环测试空字节,那么循环运行良好,并将i增加12倍(0到11),然后停止,这意味着它在第13次迭代中遇到了空字节。我不明白的是,如果我们不为其分配空间,为什么会遇到空字节?

我试图通过奇怪的字符串组合来破坏这个代码,但没有成功。我还尝试在每次对abAppend的调用中分配一个额外的字节,并对函数进行了一些更改以考虑额外的空间,它的执行与此版本完全相同。空字节的处理方式让我难以捉摸

realloc如何处理字符串中的空字节?

realloc的行为不受其管理的内存内容的影响。

但是字符串"你好"还包含终止的空字节\0。这应该是字符串的第六个也是最后一个字节,…

使用memcpy(&new[ab->size], s, len);复制字符,其中len为5。memcpy复制字符而不考虑是否存在终止的空字节。给定长度为5,它复制5个字节。它不会在这些字符后面附加一个终止的null字符。

realloc将把str放大到12个字节,但第13个字节\0没有被考虑在内。

在对abAppend调用的第二个上,在前5个字节之后,又用memcpy复制了7个字节。CCD_ 24的长度为7,并且只复制7个字节。

…它在第13次迭代中遇到了空字节。

当您测试ab.str[12]时,您超出了C标准定义行为的规则。CCD_ 26在所分配的存储器之外。它可能只包含一个空字节,因为您的进程中没有其他人将该内存用于其他目的,这就是您的循环停止的原因。如果您在之前工作过的较大程序的中间尝试这样做,那么该字节可能包含不同的值,并且您的测试可能以各种方式出错。

您最初只为字符串"中的字符分配了空间,这是正确的;你好"而不是终止的空字节,并且第二次调用只为tge字符串"中的字符添加了足够的字节;,世界;没有空终止字节。

因此,您拥有的是一个字符数组,而不是字符串,因为它不是以null结尾的。如果您随后试图读取超过分配的字节,则会触发未定义的行为,UB可以表现自己的方式之一是使事情看起来正常工作。

所以你得到了";幸运的";事情发生了,就好像你为空字节分配了空间并设置了它

最新更新