您现在的位置是:首页 >其他 >【trt_infer】 日志网站首页其他

【trt_infer】 日志

Dovake 2023-05-13 00:00:03
简介TensorRT部署封装

C++ 可变长参数

参考:

  • https://www.cnblogs.com/hanyonglu/archive/2011/05/07/2039916.html

1. C/C++语言中函数传递参数时的基本原理

在C/C++中,当我们无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表如:

void foo(...);
void foo(pram_list, ...);

参数存放在内存的堆栈段中,在执行函数的时候,从最后一个入栈,因此栈底高地址,栈顶低地址。如:

void func(int x, float y, char z);

调用函数是,实参 z 先入栈,因此在内存中变量的存放顺序为 x, y, z. 因此理论上说:只要探测到任意一个变量的地址,并且知道其他变量类型,通过指针移位操作,可以找到其他所有的输入变量

2. 可变长参数相关宏

2.1 导入头文件:

#include <stdarg.h>

2.2 相关宏定义:

typedef char* va_list;
void va_start(va_list ap, prev_param); /*ANSI version*/
type va_arg(va_list ap, type);
void va_end(va_list, ap);
  • va_list 是一个字符指针,可以理解为指向当前参数的一个指针,取参必须通过这个指针进行。

2.3 可变长参数读取的一般步骤

  • 在调用参数表之前,定义一个 va_list 类型的变量。
va_list ap;
  • 对ap 进行初始化,让它指向可变参数表里面的第一个参数,这是通过 va_start 来实现的,第一个参数是 ap 本身,第二个参数时在变参表前面紧挨的一个变量,即 “…” 之前的第一个参数。
// void foo(int arg1, int arg2, ...)
va_start(ap, arg2);
  • 获取参数。调用 va_arg, 它的第一个参数是 ap ,第二个参数是要获取参数的指定类型,然后返回这个指定类型的值,并且把 ap 的位置指向变参表的下一个变量位置。
char para = va_arg( argp, char);
  • 关闭 ap 指针。 在获取所有的参数之后,有必要将这个 ap指针关掉,以免发送危险。
void va_end ( va_list ap );

一个完整的案例:

#include <iostream>
#include <stdarg.h>
std::string format(const char* fmt, ...) {
    va_list vl;
    va_start(vl, fmt);
    char buffer[2048];
    vsnprintf(buffer, sizeof(buffer), fmt, vl);
    va_end(vl);
    return buffer;
}

void printArgs(int arg1, ...)
{
    va_list args;
    va_start(args, arg1);

    int value = arg1;
    while (value != -1)
    {
        std::cout << value << " ";
        value = va_arg(args, int);
    }

    va_end(args);
}

int main()
{
    printArgs(1, 2, 3, 4, 5, -1);
    std::cout << format("rst: %s %d", "ans:", 1) << std::endl;
    std::cout << format("rst: %s %d", "ans:", 2) << std::endl;
    std::cout << format("rst: %s %d", "ans:", 2) << std::endl;
    std::cout << format("rst: %s %d", "ans:", 3) << std::endl;
    return 0;
}
  • 输出:
1 2 3 4 5 
rst: ans: 1
rst: ans: 2
rst: ans: 2
rst: ans: 3

3. 可变长参数宏

先看一组常见的日志输出的宏:


#define INFOD(...)		iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Debug, __VA_ARGS__)
#define INFOV(...)		iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Verbose, __VA_ARGS__)
#define INFO(...)		iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Info, __VA_ARGS__)
#define INFOW(...)		iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Warning, __VA_ARGS__)
#define INFOE(...)		iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Error, __VA_ARGS__)
#define INFOF(...)		iLogger::__log_func(__FILE__, __LINE__, iLogger::LogLevel::Fatal, __VA_ARGS__)

调用方式:

INFOD("this is a log : %d %d %d", 1,2,3);
  • 此处的 __VA_ARGS __ 为可变参数的内容,可以传递到可变长函数中。
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。