【问题标题】:Can I modify a va_list before passing it on?我可以在传递之前修改 va_list 吗?
【发布时间】:2011-10-03 14:22:12
【问题描述】:

在我试图理解在 (Objective-)C 中我能用 va_list 做什么和不能做什么时,我遇到了这个小谜题。我希望在NSString 上创建一个类别,在某些情况下可以稍微简化stringWithFormat: 消息,只是为了好玩。我的目标是能够像这样使用实现:

[@"My %@ format %@!" formattedWith:@"super", @"rocks"];

希望得到一个字符串“My super format rocks!”。我的(不正确的)方法实现如下所示:

- (NSString *)formattedWith:(NSString *)arguments, ...
{
    va_list list;
    va_start(list, arguments);
    NSString *formatted = [[[NSString alloc] initWithFormat:self arguments:list] autorelease];
    va_end(list);
    return formatted;
}

现在的问题是,一旦调用了va_start(),va_list 就会被“缩短”(因为没有更好的词)并且只包含其余的参数(在示例中只有@"rocks"剩下的,加上我不关心的调用对象)。因此,传递给 initWithFormat: 消息的内容会呈现错误的结果。

关于这个问题。在我将 va_list 传递给initWithFormat: 消息之前,有没有办法修改它,这样我就可以以某种方式将第一个参数移回列表中?

我不是在寻找我自己循环遍历 va_list 的迭代过程,我希望了解 va_list 的整体限制。谢谢!

【问题讨论】:

标签: objective-c variadic-functions


【解决方案1】:

va_list 不能是modified safelyva_start 参数还需要一个参数来启动被排除的列表。解决这个问题的方法是传递一个额外的无用参数或使用可变参数宏。

//Method declaration
-(NSString*)formattedWith:(NSString*)ignored,...;

//Opt 1 (pass anything for first value)
[@"My %@ format %@!" formattedWith:nil, @"super", @"rocks"];

//Opt 2 (create a macro for the arguments)
#define VA_OPT(...) nil, ##__VA_ARGS__ //VARIADIC OPTIONAL
[@"My %@ format %@!" formattedWith:VA_OPT(@"super", @"rocks"];

//Opt 3 (just create a macro for the whole string format)
//Obviously you should just use the NSString method directly before resorting to this
#define FORMATTED_NSSTRING(str, ...) [NSString stringWithFormat:str, ##__VA_ARGS__]
FORMATTED_NSSTRING(@"My %@ format %@!", @"super", @"rocks")

【讨论】:

    猜你喜欢
    • 2023-04-02
    • 1970-01-01
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多