Assume I have a method with the signature:
+ (NSString *) myFormattedString:(NSString *)format, ...;
And I want it to prepend a string of my choice (e.g. @"Foo: "). I guess the best way is to use [myString initWithFormat:arguments:], but how would you implement this method?
I tried doing the following, but I get the warning as specified in the comment:
+ (NSString *) myFormattedString:(NSString *)format, ... {
  char *buffer;
  [format getCString:buffer maxLength:[format length] encoding:NSASCIIStringEncoding];
  va_list args;
  va_start(args, buffer); // WARNING: second parameter of 'va_start' not last named argument
  NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
  [str autorelease];
  return [NSString stringWithFormat:@"Foo: %@.", str];
}
The reason I'm assuming va_start() can take in a (char *) is because of the example I saw on the manual page of STDARG(3). Feel free to completely rewrite the method if I'm doing it totally wrong.
I think what you want is something like:
+ (NSString *) myFormattedString:(NSString *)format, ... {
  va_list args;
  va_start(args, format);
  NSString *str = [[[NSString alloc] initWithFormat:format arguments:args] autorelease];
  va_end(args);
  return [NSString stringWithFormat:@"Foo: %@.", str];
}
The stdarg.h va_* macros are used when a function (or, in this case, method) takes a variable number of arguments, as specified by "...".  va_start() is used to find the start of where the variable number of arguments begins.  As such, it needs to know a functions/methods last argument (the one just before the "...") in order to determine where the variable number of arguments starts.  This is a somewhat simplified explanation since what actually happens under the hood is very ABI/Compiler specific.  The most important point is that the second argument to va_start() is always the name of the variable 'just before the "..."'.
va_end() should be "called" (it's really a macro, not a function) for maximum portability.  Again, this whole variable arguments thing is deep, deep black magic.  Depending on the specifics of the compiler and ABI, va_end() may not do anything at all.  On the other hand, failure to use va_end() may cause your program to crash when the return statement is reached because the stack frame (if there even is one) is no longer properly set up to actually perform a return.
You've almost got it; just a couple of tweaks:
+ (NSString *) myFormattedString:(NSString *)format, ... {
  va_list args;
  va_start(args, format);
  NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
  [str autorelease];
  va_end(args);
  return [NSString stringWithFormat:@"Foo: %@.", str];
}
That should do what you're looking for.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With