提问人:mv_p 提问时间:8/13/2022 更新时间:8/14/2022 访问量:803
将缓冲区传递给函数进行写入
Passing buffer to function for writing
问:
我正在尝试实现一个快速原型程序来准备一条我打算用作 tcp 套接字通信协议的消息。 我是这方面的新手,我不太明白为什么要运行以下打印(null)。我是否未能将指针传递到子例程?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *header = "testhd";
void pack_message(char *body, char *buffer)
{
size_t body_size, msg_size, buffer_size;
char hex_size[11];
body_size = strlen(body);
snprintf(hex_size, 11, "0x%x", body_size);
msg_size = 16 + body_size;
buffer_size = msg_size + 1;
if (!buffer){
buffer = malloc(buffer_size);
}else{
buffer = realloc(buffer, buffer_size);
}
memset(buffer, 0, buffer_size);
strcat(buffer, header);
strcat(buffer, hex_size);
strcat(buffer, body);
}
int main(){
char *buffer = NULL;
char *body = "testmsg";
pack_message(body, buffer);
printf("%s", buffer);
return 0;
}
答:
0赞
WojciechS
8/13/2022
#1
请注意,函数和函数是指向同一地址的两个不同指针。
因此,在您的案例中,functiom 使用本地指针,这就是运行您的代码打印的原因。char *buffer
main
char *buffer
pack_message
NULL
pack_message
null
为了让你的代码工作,你可以采取一种方法,你把指针本身的地址作为参数传递给函数,这样函数可以看起来像这样:pack_message
main
int main(){
char *buffer = NULL;
char *body = "testmsg";
pack_message(body, &buffer);
printf("%s", buffer);
return 0;
}
您的函数应更改为:pack_message
void pack_message(char *body, char **buffer)
{
size_t body_size, msg_size, buffer_size;
char hex_size[11];
body_size = strlen(body);
snprintf(hex_size, 11, "0x%zx", body_size);
msg_size = 16 + body_size;
buffer_size = msg_size + 1;
if (NULL == *buffer){
*buffer = malloc(buffer_size);
}else{
*buffer = realloc(*buffer, buffer_size);
}
memset(*buffer, 0, buffer_size);
strcat(*buffer, header);
strcat(*buffer, hex_size);
strcat(*buffer, body);
}
请注意,我还更改了一个潜在的问题:
snprintf(hex_size, 11, "0x%zx", body_size);
由于是类型,因此使用是更好的主意,因为可以与 不同大小,有关 printf 的详细信息,请查看: https://cplusplus.com/reference/cstdio/printf/body_size
size_t
%zx
size_t
unsigned integer
可以采用类似的方法,特别是当它的值将更长的字符串时。
为了进一步改进,我建议重新设计函数以返回指向已分配缓冲区的指针,因为它将降低在不再需要时忘记释放内存的机会。char *body = "testmsg";
pack_message
评论
0赞
mv_p
8/13/2022
我之前尝试过这个(模拟通过引用传递),但我从 realloc 收到一个错误,没有意识到旧参数和新参数都需要取消引用。现在它正在工作,谢谢!只是为了澄清。检查包中的空指针(if 块),是否也应该是“if (!*pointer)”表示取消引用?
0赞
WojciechS
8/14/2022
你是对的。我错过了这一点,实际上不建议将其与布尔上下文中的处理方式相同。null
false
0赞
mv_p
8/14/2022
哦,好吧,我看到了一种非常普遍的做法,即直接测试空指针而不是 ==Null,但我想这假设 null=0 这与实现相关?
0赞
WojciechS
8/15/2022
我会说它更多的是关于可读性,因为当您看到与“NULL”的比较时,您可以更快地理解这是关于指针而不是常规变量。正如你提到的,还有一种非常非常罕见的情况,即“NULL”可能与零不同。在实践中,null 指针指向不存在的地址,因此当作为函数指针调用时,您具有未定义的行为。您可能希望在软件级别捕获此类事件,而不依赖于执行故障处理程序的硬件。
评论
&