'的va_start'用于固定args的功能

时间:2017-03-27 08:32:24

标签: objective-c macros

我有以下代码Logger.h

#import <Foundation/Foundation.h>
#import <asl.h>

#define LogDebug(format, ...){ \
  Logger(ASL_LEVEL_DEBUG, format,##__VA_ARGS__); }



#define Logger(LEVEL,format, ...) \
  LogLocal(LEVEL,format,##__VA_ARGS__);

#define LogLocal(LEVEL, format, ...) \    
  va_list arg_list; \
  va_start(arg_list, format); \
  // ...\
  va_end(arg_list); \

我将来自Obj-C的日志称为:

LogDebug(@"Name is called with flag: %@", collectName ? @"YES" : @"NO");

但是我收到错误:

  

&#39;的va_start&#39;用于固定args的功能

如何摆脱这个问题?

编辑1:

我也试着打电话:AFLogLocal(LEVEL,format,...); - 同样的错误

编辑2:

如果我删除asl_log并替换为NSLog - 它会起作用:

#define LogLocal(LEVEL,format, ...) \
NSLog((@"XXX: %s "  format), __PRETTY_FUNCTION__, ##__VA_ARGS__);

编辑3

@Amin Negm-Awad,将LogLocal替换为.m文件中的函数:

void LogLocal(int level, NSString *format, ...){

    va_list arg_list;
    va_start(arg_list, format);
    va_end(arg_list);
    NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:arg_list]; 
    asl_add_log_file(NULL, STDERR_FILENO); 
    asl_log(NULL, NULL, (level), "XXXX:  %s", [formattedString UTF8String]);     
}

按预期工作。

1 个答案:

答案 0 :(得分:3)

您使用展开的宏。但他们不会在扩展上创建范围或调用。这是一个简单的文本替换。

// Somewhere in a function
void f(void)
{
  …
  LogDebug(@"Name is called with flag: %@", collectName ? @"YES" : @"NO");
  …
 }

这将最终扩展到类似的东西:

// Somewhere in a function
void f(void)
{
  …
  // LogDebug(@"Name is called with flag: %@", collectName ? @"YES" : @"NO");
  va_list arg_list;
  va_start(arg_list, @"Name is called with flag: %@");
  // ...
  va_end(arg_list);
  …
 }

由于f()没有vargs,因此没有vargs。

LogLocal()作为一个函数可能会有所帮助,而不是宏:

void LogLocal( int level, NSString *format, ... );

实现:

void LogLocal( int level, NSString *format, ... )
{
  va_list arg_list; 
  va_start(arg_list, format); 
  // ...
  va_end(arg_list);
}

到你的编辑2:

是的,这是有效的,因为你没有触摸arg列表,而是将args传递给一个带vargs的函数。但你不需要这个技巧。而是使LogLocal()成为一个函数,它将被调用类似于NSLog()而没有任何错误。