我的环境:Xcode5,iOS,Objective-C / Objective-C ++混合。
我试图找出导致下一个问题的原因。我正在编写自己的日志功能:
int _me_log(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
char *c = va_arg(args, char *);
char *message = NULL;
printf(fmt, args);
int n = asprintf(&message, fmt, args);
if (n != -1 && message != NULL) {
//do something with 'message' like writing to file, etc.
UPDATE:
//we need to handle memory created for 'message' storage.
free(message);
}
va_end(args);
return n;
}
然后我称之为:
_me_log("socket %s did open", "Socket: 0x1fd1c880");
而不是正确的输出socket Socket: 0x1fd1c880 did open
我在这行socket \\323\331/ did open
中得到了一些像这个printf(fmt, args);
一样的胡言乱语。
如果我这样称呼printf("%s", c);
我会得到正确的结果。
答案 0 :(得分:2)
您有正确的想法在这里使用va_list
,但如果您使用va_list
,则应使用vasprintf
代替asprintf
:
int _me_log(const char *fmt, ...)
{
va_list args;
char *message = NULL;
int n;
va_start(args, fmt);
n = vasprintf(&message, fmt, args);
if (n != -1 && message != NULL) {
// ... use message ...
}
free(message);
va_end(args);
return n;
}
对于printf
系列的每个例程,有一个变体采用va_list
而不是变量参数...
,其名称前缀为v
字母,例如:
int printf(const char *format, ...);
int vprintf(const char *format, va_list ap);
这些例程存在,因此您可以为xprintf
编写自己的(非宏)包装器。
答案 1 :(得分:1)
似乎是一个非常复杂的实现。尝试:
int _me_log(const char *fmt, ...) {
int ret = 0;
va_list va;
va_start(va, fmt);
ret = vprintf(fmt, va);
va_end(va);
putc('\n', stdout);
return ret;
}
但是,当然,除了强制换行之外,这与printf()
没有区别。