您现在的位置是:首页 >其他 >【trt_infer】 日志网站首页其他
【trt_infer】 日志
                简介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 __ 为可变参数的内容,可以传递到可变长函数中。
 
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。
        
    
        
    
            




U8W/U8W-Mini使用与常见问题解决
QT多线程的5种用法,通过使用线程解决UI主界面的耗时操作代码,防止界面卡死。...
stm32使用HAL库配置串口中断收发数据(保姆级教程)
分享几个国内免费的ChatGPT镜像网址(亲测有效)
Allegro16.6差分等长设置及走线总结