在 C++ 宏中正确 string/char 转换
Proper string/char casting in C++ macro
我继承了一些导致大量编译器警告的代码,并且我不是一个足够强大的 C++ 程序员来弄清楚如何正确解决它。即:
log.h:
#include <stdarg.h>
#include <libgen.h>
#include <errno.h>
#include <string.h>
void log(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
#define error(fmt, ...) ow_log("ERROR[%s:%s()@%d]: " fmt, basename(__FILE__), __func__, __LINE__, ##__VA_ARGS__)
#define sys_error(fmt, ...) ow_log("ERROR[%s:%s()@%d]: System error: %s:" fmt, basename(__FILE__), __func__, __LINE__, strerror(errno), ##__VA_ARGS__)
log.cpp
#include <stdarg.h>
#include <stdio.h>
#include <pthread.h>
void log(const char* fmt, ...)
{
time_t t = time(NULL);
struct tm tm = *localtime(&t);
printf("%04d-%02d-%02d %02d:%02d:%02d ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
printf("\n");
fflush(stdout);
va_end(args);
}
使用示例:
int args = 6;
log("Some string not explicitly typed with %i interpolated arguments", args);
error("Something went wrong here");
C++ 程序员可能会立即看到它,但我看不到。每当使用它时我得到的是:
log.h:11:79: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
#define error(fmt, ...) log("ERROR[%s:%s()@%d]: " fmt, basename(__FILE__), __func__, __LINE__, ##__VA_ARGS__)
^
看起来代码已经这样有一段时间了,而且我没有看到任何非常糟糕的不良影响,但这使得读取编译器输出变得非常困难(并且似乎实际上 错误),所以我试图修复它。我尝试了一些不同的转换策略,但似乎没有任何效果,我想我误解了宏的工作原理以及它使用的所有内置函数。
根据this page,basename() 的原型是
char *basename(char *path);
文档说:
The basename() function may modify the string pointed to by path, and may return a pointer to static storage that may then be overwritten by a subsequent call to basename().
因此,您不应将字符串文字传递给此函数。
您应该使用的函数是
char * basename_r(const char *path, char *bname);
其中 bname 是要使用的函数的临时存储。
我继承了一些导致大量编译器警告的代码,并且我不是一个足够强大的 C++ 程序员来弄清楚如何正确解决它。即:
log.h:
#include <stdarg.h>
#include <libgen.h>
#include <errno.h>
#include <string.h>
void log(const char* fmt, ...) __attribute__((format (printf, 1, 2)));
#define error(fmt, ...) ow_log("ERROR[%s:%s()@%d]: " fmt, basename(__FILE__), __func__, __LINE__, ##__VA_ARGS__)
#define sys_error(fmt, ...) ow_log("ERROR[%s:%s()@%d]: System error: %s:" fmt, basename(__FILE__), __func__, __LINE__, strerror(errno), ##__VA_ARGS__)
log.cpp
#include <stdarg.h>
#include <stdio.h>
#include <pthread.h>
void log(const char* fmt, ...)
{
time_t t = time(NULL);
struct tm tm = *localtime(&t);
printf("%04d-%02d-%02d %02d:%02d:%02d ", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
printf("\n");
fflush(stdout);
va_end(args);
}
使用示例:
int args = 6;
log("Some string not explicitly typed with %i interpolated arguments", args);
error("Something went wrong here");
C++ 程序员可能会立即看到它,但我看不到。每当使用它时我得到的是:
log.h:11:79: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]
#define error(fmt, ...) log("ERROR[%s:%s()@%d]: " fmt, basename(__FILE__), __func__, __LINE__, ##__VA_ARGS__)
^
看起来代码已经这样有一段时间了,而且我没有看到任何非常糟糕的不良影响,但这使得读取编译器输出变得非常困难(并且似乎实际上 错误),所以我试图修复它。我尝试了一些不同的转换策略,但似乎没有任何效果,我想我误解了宏的工作原理以及它使用的所有内置函数。
根据this page,basename() 的原型是
char *basename(char *path);
文档说:
The basename() function may modify the string pointed to by path, and may return a pointer to static storage that may then be overwritten by a subsequent call to basename().
因此,您不应将字符串文字传递给此函数。
您应该使用的函数是
char * basename_r(const char *path, char *bname);
其中 bname 是要使用的函数的临时存储。