可变参数包装器

精液

为了输出格式化的调试输出,我为编写了包装器vsfprint现在,我想为输出缓冲区分配足够的内存,而不是仅仅声称随机的高缓冲区大小(这是一个小型嵌入式平台(ESP8266))。为此,我遍历变量参数,直到找到NULL。

只要我不忘记(char *)NULL为每个调用添加参数,就可以正常工作。因此,我认为,让我们创建另一个包装器,一个仅中继所有参数并添加(char *) NULL参数的函数:

#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h> // malloc

void write_log(const char *format, ...) {

  char* buffdyn;
  va_list args;

  //  CALC. MEMORY
  size_t len;
  char *p;

  if(format == NULL)
    return;

  len = strlen(format);

  va_start(args, format);

  while((p = va_arg(args, char *)) != NULL)
    len += strlen(p);

  va_end(args);
  // END CALC. MEMORY

  // ALLOCATE MEMORY
  buffdyn = malloc(len + 1);    /* +1 for trailing \0 */
  if(buffdyn == NULL) {
    printf("Not enough memory to process message.");
    return;
  }

  va_start(args, format);
  //vsnprintf = Write formatted data from variable argument list to sized buffer
  vsnprintf(buffdyn, len, format, args);
  va_end(args);

  printf("%s\r\n",buffdyn);
  free(buffdyn);
}

void write_log_wrapper(const char *format, ...) {

  va_list arg;

  va_start(arg, format);
  write_log(format,arg,(char *)NULL);
  va_end(arg);
}


int main()
{
    const char* sDeviceName = "TEST123";
    const char* sFiller1 = "12345678";

    write_log_wrapper("Welcome to %s%s", sDeviceName,sFiller1);
    write_log("Welcome to %s%s", sDeviceName,sFiller1, (char *)NULL);

    return 0;
}

write_log()直接调用该函数可以正常工作(如果您不忘记NULL参数)。调用该write_log_wrapper()函数将仅显示第一个参数,然后在输出中添加“(nu)(垃圾?)”。

我究竟做错了什么?这是一种很好的方式来实现我最初打算做的事情吗?

谢谢。

安德鲁·亨利(Andrew Henle)

为了确定容纳输出字符串所需的缓冲区大小,您需要完全解析整个格式字符串并实际扩展arguments

您可以自己进行操作,复制和处理所有内容,printf()并希望不会出错,或者可以使用vsnprintf()-首先确定大小,然后将输入实际扩展为一个输出字符串。

#define FIXED_SIZE 64

void write_log(const char *format, ...)
{
    // set up a fixed-size buffer and a pointer to it
    char fixedSizeBuffer[ FIXED_SIZE ];
    char *outputBuffer = fixedSizeBuffer;

    // no dynamic buffer yet
    char *dynamicBuffer = NULL;

    // get the variable args
    va_list args1;
    va_start( args1, format );

    // need to copy the args even though we won't know if we
    // need them until after we use the first set
    va_list args2;
    va_copy( args2, args1 );

    // have to call vsnprintf at least once - might as well use a small
    // fixed-size buffer just in case the final string fits in it
    int len = vsnprintf( fixedSizeBuffer, sizeof( fixedSizeBuffer ), format, args1 );
    va_end( args1 );

    // it didn't fit - get a dynamic buffer, expand the string, and
    // point the outputBuffer pointer at the dynamic buffer so later
    // processing uses the right string
    if ( len > sizeof( fixedSizeBuffer  ) )
    {
        dynamicBuffer = malloc( len + 1 );
        vsnprintf( dynamicBuffer, len + 1, format, args2 );
        outputBuffer = dynamicBuffer;
    }

    va_end( args2 );

    // do something with outputBuffer

    free( dynamicBuffer );
    return;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么Java包装器类是不可变的?

Java包装器类真的是不可变的吗?

如何包装带有可变参数的函数

用可变参数模板在C ++中包装函数指针

Swig包装器用于可变的参数长度

可变参数constexpr类型选择器

如何将std :: function包装器转换为可变参数?

如何使用SWIG使用可变参数包装C函数

如何使用LD_PRELOAD包装可变参数函数?

值包装器的可变参数模板构造函数的类构造函数优先级

将可变参数模板包装为元组向量

考虑参考和const的可变函数包装器

使用可变参数模板(gcc,clang)的成员函数指针包装器

如何评估从装饰器的包装器中调用的函数的参数?

C ++ 17:使用通用可变参数lambda包装可调用

使用可变参数模板进行C回调包装

如何在SWIG中包装可变参数模板类的可变参数模板成员函数?

如何使用可变参数模板编写通用函数包装器

迭代器的通用可变和非可变参数

迭代器的通用可变和非可变参数

在Typescript中包装可变参数元组类型

将std :: variant的包装器的std :: vector传递给可变参数类,在不知道具体细节的情况下包装可变参数方法

如何包装采用可变长度参数的方法?

在可变函数的包装器中中继可选参数

替换参数包的包装器类型

有关C ++代码的一些说明(lambda包装器和可变参数模板)

如何获得包装的可变参数类型?

为类创建一个包装器以避免字节中的可变参数

控制器参数的 Spring 注释包装器