开发者

Can I modify a va_list before passing it on?

In my attempts to understand what I can and can't do with a va_list in (Objective-)C, I came across this little puzzle. I was hoping to create a category on NSString that would simplify the stringWithFormat: message a bit in some cases, just for the fun of it. What I was aiming for was being able to use the implementation like this:

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

Hoping to end up with a string saying "My super format rocks!". My (incorrect) method implementation looks like this:

- (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;
}

Now the problem is that as soon 开发者_运维技巧as va_start() is called, the va_list is 'shortened' (for lack of a better word) and only contains the rest of the arguments (in the case of the example only @"rocks" remains, plus the calling object which I don't care about). What's passed onto the initWithFormat: message therefore renders the wrong kind of result.

On to the question. Are there ways to modify the va_list before I pass it to the initWithFormat: message, so I can somehow shift the first argument back onto the list?

I'm not looking for an iterative process where I loop through the va_list myself, I'm looking to understand the limits of va_list as a whole. Thanks!


The va_list can not be modified safely. The va_start argument also requires an argument to start the list which is excluded. The ways to work around this are to either pass an additional useless argument or use variadic macros.

//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")
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜