变长参数的函数写法

//*****************************************************************************************
//                Template No. SWF0012   Template Version No. 04.04.00
//
//*****************************************************************************************
//   FUNCTION NAME    : PrintLog()
//
//-------------------------------------------------- PURPOSE -----------------------------------------
//
//     Print a text in log file
//---------------------------------------- $$ REQUIREMENTS $$ ----------------------------------------
//
//  Format: $${TAG} R[#][Prod. ID]:Specification Path
//
//               $$:    ISGcq00622453
//                TAG:    [APP_GEN]
//              R #:    R[29]
//            Prod.ID: 
//        Spec. Path:   /vob/
//
//
//
//-------------------- PSEUDO CODE / DETAILED FUNCTION DESCRIPTION -------------------
//
//            Creates a log file with the phone info
//
//------------------------------------------------ REVISIONS ------------------------------------------
// Date       Name                 Tracking #     Description
// ---------  -------------------  -------------  ------------------------------
// 26ARP2011  Feng Liu             ISGcq00622453  Initial Creation
//*****************************************************************************************************
//
//----------------------------------------- FUNCTION DEFINITION ---------------------------------------
void FeatureDisableDlg::PrintLog(CString& message)
{
    if(APPLICATION_VERSION[0] != 'R')
    {
        try
        {
            //verify if it is already opened
            if (m_logFile.m_hFile == CFile::hFileNull)
            {
                if(m_logFile.Open(LOG_FILE_NAME,
                        CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite))
                {
                    m_logFile.SeekToEnd();
                    CString log;
                    log.Format("=====================================================/n",log);
                    time_t rawtime;
                    time ( &rawtime );
                    char timeStr[0x100];

                    if(!ctime_s(timeStr, 0x100, &rawtime)) {
                        log.Format("Execution date: %s", timeStr);
                    } else {
                        log.Format("Execution date: %s", "Can not read the time.");
                    }

                    m_logFile.Write(log, log.GetLength());
                }
            }
            m_logFile.Write(message, message.GetLength());
        }
        catch (...)
        {
        }
    }
}void FeatureDisableDlg::PrintLog(const char* message, ...)
{
//  if(APPLICATION_VERSION[0] != 'R')
  if(1)
  {
      va_list list;
      va_start(list, message);
      char szBuffer[MAX_OUTPUT_TEXT_SIZE];
      _vsnprintf_s(szBuffer, sizeof(szBuffer), message, list);

      CString log(szBuffer);
      PrintLog(log);

      va_end(list);
  }
}

发表于 @ 2011年04月26日 10:13:00 | 评论( 0 ) | 编辑| 举报| 收藏

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/asiainfolf/archive/2011/04/26/6363397.aspx

<think>嗯,用户想了解C语言中宏的变长参数的使用方法和示例。首先,我得回忆一下C语言里宏支持变长参数的语法。记得在C99标准之后,宏可以用`...`表示可变参数,然后用`__VA_ARGS__`来引用这些参数。比如`#define LOG(fmt, ...) printf(fmt, __VA_ARGS__)`这样的写法。 不过用户提到的引用中有提到x-macros和一些宏的高级用法,可能需要结合这些内容。比如引用[2]里提到宏的几种常用语法,特别是可变参数宏的部分。另外,用户的问题还涉及到可变参数函数,像printf这样的函数,但用户现在关注的是宏,所以需要区分函数和宏的不同处理方式。 首先,我应该解释清楚可变参数宏的基本语法,比如使用`...`和`__VA_ARGS__`,并给出一个简单的例子,比如打印日志的宏。然后,可能需要提到在C99和C11中的不同,比如C11允许使用更可读的名字代替`__VA_ARGS__`,比如`#define LOG(fmt, args...) printf(fmt, args)`,但要注意兼容性问题。 另外,用户提供的引用[5]提到格式化串中的%号数量对应参数数量,这在宏中可能需要特别注意,因为宏展开时不会检查类型和数量是否正确,这可能导致运行时错误。所以需要提醒用户在使用时确保参数匹配。 可能还需要提到空参数的情况,比如当可变参数为空时,直接使用`__VA_ARGS__`可能会导致编译错误,这时可以使用`##__VA_ARGS__`来处理,这在GCC和Clang中是支持的,但C标准可能有不同规定,需要说明。 然后,给出几个示例,比如基础用法、带格式化字符串的日志宏、支持空参数的情况,以及C11中的命名参数。同时,要结合引用中的内容,比如引用[3]提到可变参数函数在日志记录中的应用,所以宏的例子也可以举日志的例子,这样更贴近实际应用。 还需要注意,宏和函数的区别,比如宏是在预处理阶段展开,而函数是在运行时调用。可变参数宏可以提供更灵活的代码生成,但也可能带来调试上的困难,需要适当提醒用户。 最后,生成相关问题时要考虑用户可能的后续问题,比如与可变参数函数的配合使用、兼容性问题、调试技巧等。这样能帮助用户更全面地理解宏的变长参数用法。</think>### C语言宏的变长参数使用方法详解 C语言中宏的变长参数功能在C99标准后正式支持,允许开发者创建灵活的参数传递机制,以下是具体使用方法和示例: #### 一、基本语法格式 ```c #define 宏名(固定参数, ...) 替换文本中使用__VA_ARGS__ ``` 这里的`...`表示接受任意数量参数,`__VA_ARGS__`是预定义宏,展开时会替换为实际传入的参数[^2][^5] #### 二、核心使用场景 1. 日志输出系统 2. 类型安全的泛型编程 3. 代码调试辅助工具 4. 代码模板生成 #### 三、典型示例代码 1. **基础用法示例** ```c #define DEBUG_LOG(...) printf(__VA_ARGS__) // 使用示例 DEBUG_LOG("Value: %d, Name: %s\n", 42, "test"); // 展开为printf("Value: %d, Name: %s\n",42,"test") ``` 2. **带固定参数的格式化日志** ```c #define FORMAT_LOG(fmt, ...) fprintf(stderr, "[LOG] " fmt "\n", __VA_ARGS__) // 使用示例 FORMAT_LOG("Process %s with code %d", "startup", 200); ``` 3. **支持空参数的变体**(GCC/Clang扩展) ```c #define SAFE_LOG(fmt, ...) printf(fmt, ##__VA_ARGS__) // 使用示例 SAFE_LOG("System ready\n"); // 正确处理无额外参数的情况 ``` 4. **C11标准命名参数**(更直观的写法) ```c #define LOG(fmt, args...) printf(fmt, args) // 使用示例 LOG("Temperature: %.1f°C\n", 25.5); ``` #### 四、注意事项 1. 参数数量必须与格式化字符串占位符匹配,否则会导致运行时错误 2. 在C99标准下,空参数需要配合`##`运算符处理(编译器扩展) 3. 建议在复杂场景中配合`_Generic`选择器实现类型安全 4. 调试时建议使用`gcc -E`查看宏展开结果 #### 五、与函数的配合使用 可变参数宏常与`va_list`系列函数搭配使用,例如: ```c #define INIT_LOG(...) init_logger(__FILE__, __LINE__, __VA_ARGS__) void init_logger(const char* file, int line, const char* fmt, ...) { va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值