c++ 内置宏

内置类型的最大值宏定义


本文地址: http://blog.csdn.NET/caroline_wendy/article/details/24311895


C++中, 经常会使用, 某些类型的最大值, 如int的最大整数(INT_MAX), C的函数中, 包含了这些宏定义.

头文件: #include <climits>

具体参见:

nameexpressesvalue*
CHAR_BITNumber of bits in a char object (byte)8 or greater*
SCHAR_MINMinimum value for an object of type signed char-127 (-27+1) or less*
SCHAR_MAXMaximum value for an object of type signed char127 (27-1) or greater*
UCHAR_MAXMaximum value for an object of type unsigned char255 (28-1) or greater*
CHAR_MINMinimum value for an object of type chareither SCHAR_MIN or 0
CHAR_MAXMaximum value for an object of type chareither SCHAR_MAX or UCHAR_MAX
MB_LEN_MAXMaximum number of bytes in a multibyte character, for any locale1 or greater*
SHRT_MINMinimum value for an object of type short int-32767 (-215+1) or less*
SHRT_MAXMaximum value for an object of type short int32767 (215-1) or greater*
USHRT_MAXMaximum value for an object of type unsigned short int65535 (216-1) or greater*
INT_MINMinimum value for an object of type int-32767 (-215+1) or less*
INT_MAXMaximum value for an object of type int32767 (215-1) or greater*
UINT_MAXMaximum value for an object of type unsigned int65535 (216-1) or greater*
LONG_MINMinimum value for an object of type long int-2147483647 (-231+1) or less*
LONG_MAXMaximum value for an object of type long int2147483647 (231-1) or greater*
ULONG_MAXMaximum value for an object of type unsigned long int4294967295 (232-1) or greater*
LLONG_MINMinimum value for an object of type long long int-9223372036854775807 (-263+1) or less*
LLONG_MAXMaximum value for an object of type long long int9223372036854775807 (263-1) or greater*
ULLONG_MAXMaximum value for an object of type unsigned long long int18446744073709551615 (264-1) or greater*
<think>我们正在讨论C++中的日志宏实现。根据引用内容,日志宏主要用于调试和记录程序运行信息,可以输出到文件或控制台。引用中提供了几个示例,包括简单的日志宏和分级日志宏(如INFO、DEBUG、ERROR级别)。下面我将结合这些引用,逐步解释如何实现和使用C++日志宏。 ### 1. 基本日志宏 一个最简单的日志宏可以定义为: ```cpp #include <iostream> #include <fstream> // 定义一个简单的日志宏,输出到控制台 #define LOG(msg) std::cout << msg << std::endl // 或者输出到文件 #define LOG_TO_FILE(msg) do { \ std::ofstream logfile("log.txt", std::ios::app); \ if (logfile.is_open()) { \ logfile << msg << std::endl; \ logfile.close(); \ } \ } while(0) ``` 使用示例: ```cpp int main() { LOG("This is a log message to console."); LOG_TO_FILE("This is a log message to file."); return 0; } ``` ### 2. 分级日志宏 引用[2]和[3]提到了分级日志宏(如INFO、DEBUG、ERROR)。我们可以通过定义不同级别的宏,并在编译时通过宏定义(如`DEBUG`)来控制是否输出某些级别的日志。 ```cpp // 日志级别枚举(可选) enum LogLevel { DEBUG, INFO, ERROR }; // 根据日志级别输出,并支持格式化字符串(似printf) #define LOG(level, format, ...) do { \ if (level >= current_log_level) { \ printf("[%s] %s:%d: " format "\n", \ levelToString(level), __FILE__, __LINE__, ##__VA_ARGS__); \ } \ } while(0) // 将日志级别枚举转换为字符串 const char* levelToString(LogLevel level) { switch(level) { case DEBUG: return "DEBUG"; case INFO: return "INFO"; case ERROR: return "ERROR"; default: return "UNKNOWN"; } } // 设置当前日志级别(全局变量) LogLevel current_log_level = INFO; ``` 但是,更常见的做法是为每个级别定义单独的宏,这样使用更方便: ```cpp #define DEBUG_LOG(format, ...) LOG(DEBUG, format, ##__VA_ARGS__) #define INFO_LOG(format, ...) LOG(INFO, format, ##__VA_ARGS__) #define ERROR_LOG(format, ...) LOG(ERROR, format, ##__VA_ARGS__) ``` 其中,`LOG`宏可以定义为: ```cpp #define LOG(level, format, ...) do { \ if (level >= current_log_level) { \ printf("[%s] %s:%d: " format "\n", \ levelToString(level), __FILE__, __LINE__, ##__VA_ARGS__); \ } \ } while(0) ``` 注意:`##__VA_ARGS__`用于处理可变参数,当可变参数为空时,可以消除前面的逗号(GCC和Clang支持,MSVC可能需要调整)。 ### 3. 线程安全的日志宏 在多线程环境下,我们需要确保日志输出是线程安全的。引用[4]中提到了使用互斥锁(mutex)来保护日志写入。下面是一个线程安全的日志宏示例: ```cpp #include <iostream> #include <fstream> #include <mutex> std::mutex log_mutex; #define THREAD_SAFE_LOG(msg) do { \ std::lock_guard<std::mutex> lock(log_mutex); \ std::cout << msg << std::endl; \ } while(0) // 或者写入文件 #define THREAD_SAFE_LOG_TO_FILE(msg) do { \ std::lock_guard<std::mutex> lock(log_mutex); \ std::ofstream logfile("log.txt", std::ios::app); \ if (logfile.is_open()) { \ logfile << msg << std::endl; \ logfile.close(); \ } \ } while(0) ``` ### 4. 使用示例 结合分级和线程安全的日志宏,我们可以这样使用: ```cpp int main() { // 设置日志级别为DEBUG(输出所有级别的日志) current_log_level = DEBUG; DEBUG_LOG("Debug message: %d", 42); INFO_LOG("Info message"); ERROR_LOG("Error message: %s", "File not found"); return 0; } ``` ### 注意事项 1. **可变参数宏**:使用`__VA_ARGS__`时,注意不同编译器的兼容性。在GCC和Clang中,可以使用`##__VA_ARGS__`来支持零个额外参数;在MSVC中,可能需要使用`__VA_ARGS__`并确保至少有一个参数(可以通过添加一个空参数来解决)。 2. **性能考虑**:在日志宏中,尤其是在低日志级别(如DEBUG)时,如果日志输出被关闭,应避免计算日志参数。可以使用宏条件判断来避免不必要的计算。例如: ```cpp #ifdef ENABLE_DEBUG_LOG #define DEBUG_LOG(format, ...) LOG(DEBUG, format, ##__VA_ARGS__) #else #define DEBUG_LOG(format, ...) // 定义为空,编译器会优化掉 #endif ``` 3. **输出到文件**:频繁打开和关闭文件可能会影响性能。可以考虑在程序开始时打开文件,并在程序结束时关闭,或者使用一个日志线程来异步写入(引用[4]中提到了线程池)。 ### 总结 C++日志宏的实现可以根据需求定制,从简单的控制台输出到复杂的多线程文件写入。通过宏和可变参数,我们可以创建灵活且易于使用的日志系统。在实际项目中,还可以考虑使用现成的日志库(如spdlog、glog等),它们提供了更完善的功能。 §§相关问题§§ 1. 如何实现一个支持不同日志级别(如DEBUG、INFO、ERROR)的日志宏? 2. 在多线程程序中如何保证日志输出的线程安全? 3. 如何避免在日志宏中因参数计算而导致的性能损失? 4. 如何将日志输出到文件而不是控制台? 5. 有哪些成熟的C++日志库可以替代自己实现日志宏?</think>### C++日志宏的实现与使用方法 #### 一、基本日志宏实现 ```cpp #include <cstdio> // 基础日志宏(输出到控制台) #define LOG(fmt, ...) printf("[LOG] %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) // 使用示例 int main() { int x = 42; LOG("程序启动"); // 输出: [LOG] filename.cpp:行号: 程序启动 LOG("x的值 = %d", x); // 支持格式化参数 } ``` **说明**: 1. `__FILE__`和`__LINE__`是编译器内置宏,自动获取文件名和行号 2. `##__VA_ARGS__`处理可变参数(GCC/Clang扩展) 3. 输出格式:`[LOG] 文件名:行号: 用户消息` #### 二、分级日志系统(带级别控制) ```cpp #include <cstdio> // 日志级别枚举 enum LogLevel { DEBUG, INFO, WARN, ERROR }; // 全局日志级别控制 LogLevel g_log_level = INFO; // 分级日志宏 #define LOG(level, fmt, ...) do { \ if (level >= g_log_level) { \ const char* prefix = ""; \ switch(level) { \ case DEBUG: prefix = "[DEBUG]"; break; \ case INFO: prefix = "[INFO]"; break; \ case WARN: prefix = "[WARN]"; break; \ case ERROR: prefix = "[ERROR]"; break; \ } \ printf("%s %s:%d: " fmt "\n", prefix, __FILE__, __LINE__, ##__VA_ARGS__); \ } \ } while(0) // 快捷宏 #define DLOG(fmt, ...) LOG(DEBUG, fmt, ##__VA_ARGS__) #define ILOG(fmt, ...) LOG(INFO, fmt, ##__VA_ARGS__) #define WLOG(fmt, ...) LOG(WARN, fmt, ##__VA_ARGS__) #define ELOG(fmt, ...) LOG(ERROR, fmt, ##__VA_ARGS__) // 使用示例 int main() { g_log_level = DEBUG; // 设置日志级别 DLOG("调试信息: %f", 3.14); // 输出调试信息 ILOG("普通信息"); ELOG("错误发生: %s", "文件未找到"); } ``` #### 三、线程安全日志宏(带互斥锁) ```cpp #include <iostream> #include <fstream> #include <mutex> std::mutex g_log_mutex; std::ofstream g_logfile("app.log", std::ios::app); // 线程安全日志宏 #define SAFE_LOG(fmt, ...) do { \ std::lock_guard<std::mutex> lock(g_log_mutex); \ if (g_logfile.is_open()) { \ g_logfile << "[" << __FILE__ << ":" << __LINE__ << "] "; \ g_logfile << fmt << "\n"; \ } \ } while(0) // 使用示例 void worker() { SAFE_LOG("线程 %d 启动", std::this_thread::get_id()); } ``` #### 四、高级特性实现 1. **条件日志**(仅在调试模式生效): ```cpp #ifdef _DEBUG #define DEBUG_LOG(fmt, ...) LOG(fmt, ##__VA_ARGS__) #else #define DEBUG_LOG(fmt, ...) // 空宏 #endif ``` 2. **自动添加时间戳**: ```cpp #include <chrono> #include <iomanip> #define TIMESTAMP_LOG(fmt, ...) do { \ auto now = std::chrono::system_clock::now(); \ auto t = std::chrono::system_clock::to_time_t(now); \ std::cout << std::put_time(std::localtime(&t), "%F %T "); \ LOG(fmt, ##__VA_ARGS__); \ } while(0) ``` #### 五、最佳实践建议 1. **生产环境建议**: - 使用成熟日志库(如spdlog、glog)替代手写宏 - 异步日志写入避免阻塞主线程[^4] - 日志分级过滤(如生产环境仅保留ERROR以上级别) 2. **性能优化**: ```cpp // 编译期禁用低级别日志 #if LOG_LEVEL < 2 #define DEBUG_LOG(...) #endif ``` 3. **错误处理**: ```cpp #define CHECK(condition) \ if (!(condition)) ELOG("检查失败: %s", #condition) ``` **典型应用场景**: - 调试复杂逻辑时追踪变量变化 - 记录程序关键执行路径 - 多线程环境下的行为分析 - 生产环境错误追踪[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值