字符数组 vs 字符指针

6
当使用 recv 通过套接字接收数据时,我注意到以下代码:
char buffer[4];
memset(buffer, 0, 4);
recv(socket, buffer, 4, 0);
我接收到的是 "mesgx��",其中 "mesg" 是我发送的内容,后面附加了一些随机字符。
如果我使用以下代码:
char * method = (char *) malloc(4);
memset(buffer, 0, 4);
recv(socket, buffer, 4, 0);
我接收到的是 "mesg",没有随机字符附加在我的字符串末尾。我发现如果我使用 char[5],它也可以正常工作,但我不太明白为什么。malloc(4) 真的会分配 5 个字节吗?第五个字节是 NUL 吗?
4个回答

16

malloc(4)函数调用实际上只分配了四个字节的内存。巧合的是,在内存中下一个字节刚好是一个NUL,这导致你的字符串被终止了。

如果你在栈上分配了char buffer[4],那么下一个字节恰好是一个'x',后面跟着其他一些内容,所以你的字符串会一直继续直到找到下一个NUL字节为止。

Socket函数只处理字节,并不将它们视为带有尾随NUL或其他额外内容的字符串。你得到了你所请求的东西。


6

您需要5个字符才能正确地以NULL结尾。终止的NULL算作一个字符,因此如果我们需要N个字符,则应分配N+1个字符。反之,对于分配的N个字符,您可以使用N-1个字符。


3
我怀疑这个差异只是巧合。当您将缓冲区用作字符串时,例如在printf()中,它将被读取超过其限制,直到找到'\0'为止。
在这两种情况下,您应该使用buffer[5]或malloc(5)。memset()不应该是必要的,最好在recv()之后放置buffer[4] = '\0'。

2
你只请求recv将最多4个字节放入你的缓冲区,因此你不可能收到超过4个char。应该检查recv的返回值以查看实际返回了多少字节。
我怀疑问题在于你没有仔细验证从生成输出的任何例程中是否仅输出了4个char。一种显示可能未以空字符结尾的char缓冲区初始内容的方法如下。
printf("%.4s\n", buffer);

一个完整的recv调用片段可能是这样的:
#define MAX_BUF_LEN (512)
char buffer[MAX_BUF_LEN];
ssize_t count = recv(socket, buffer, MAX_BUF_LEN, 0);

if (count > 0)
    printf("%.*s\n", count, buffer);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接