Can I change va_list before passing it?

In my attempts to understand what I can and cannot do with va_list in (Objective-) C, I came across this little mystery. I was hoping to create a category on NSString that in some cases will simplify the stringWithFormat: message, just for fun. What I was aiming for was able to use the implementation as follows:

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

We hope that the line with the inscription " My super format rocks! " My super format rocks! . My (incorrect) implementation of the method is as follows:

 - (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, va_list is "shortened" (due to the lack of a better word) and contains only the rest of the arguments (in the case of just an example, @"rocks" remains, plus the calling object that I'm not interested in) . Thus, the message passed to the initWithFormat: message does the wrong result.

To the question. Are there any ways to change va_list before passing it to the initWithFormat: message so that I can somehow transfer the first argument back to the list?

I'm not looking for an iterative process, when I scroll through va_list myself, I'm looking to understand the limits of va_list in general. Thanks!

+6
source share
1 answer

va_list cannot be changed safely . The va_start argument also requires an argument to start the list, which is excluded. Ways to get around this are to either pass an additional useless argument, or use variable 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") 
+4
source

Source: https://habr.com/ru/post/898523/


All Articles