【问题标题】:Passing buffer to function for writing将缓冲区传递给函数以进行写入
【发布时间】:2022-08-14 05:21:34
【问题描述】:

我正在尝试实现一个快速原型程序来准备一条我打算用作 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;
}
  • 请记住,C 中的参数是通过按价值.这意味着调用中的值是复制了进入函数局部参数变量。对局部参数变量的任何更改,例如分配给它,只会发生在该局部变量上。调用中使用的原始值不会受到影响。请研究在 C 中模拟通过引用传递.提示:它涉及指针和指向运算符&amp;
  • 当你弄清楚缓冲区问题后,你仍然需要处理释放分配的块(否则程序会泄漏内存......)
  • 你不能在调用者中声明(或分配)一个足够大的缓冲区,然后让你的\'pack\'函数尽可能多地填充(不溢出!)吗?

标签: c pointers memory-management dynamic malloc


【解决方案1】:

请注意main函数中的char *bufferpack_message函数中的char *buffer是两个不同的指针,它们指向同一个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);

由于body_size 的类型为size_t,因此最好使用%zx,因为size_t 的大小可以与unsigned integer 不同,有关printf 的详细信息请查看:https://cplusplus.com/reference/cstdio/printf/

可以对char *body = "testmsg"; 采取类似的方法,尤其是当它的值将是更长的字符串时。 为了进一步改进,我建议重新设计pack_message 函数以返回指向已分配缓冲区的指针,因为它会降低在不再需要时忘记释放内存的机会。

【讨论】:

  • 我之前曾尝试过(模拟通过引用传递),但我从 realloc 得到一个错误,没有意识到旧参数和新参数都需要取消引用。现在它正在工作,谢谢!只是为了澄清。检查包中的空指针(if 块),是否也应该是“if (!*pointer)”,意思是取消引用?
  • 你说的对。我错过了这一点,实际上不建议在布尔上下文中将nullfalse 相同。
猜你喜欢
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
  • 2023-03-22
  • 2013-12-09
  • 1970-01-01
  • 2016-02-06
相关资源
最近更新 更多