7

假设我有一个带有签名的方法:

+ (NSString *) myFormattedString:(NSString *)format, ...;

我希望它在我选择的字符串前面添加(例如@“Foo:”)。我想最好的方法是使用 [myString initWithFormat:arguments:],但是你将如何实现这个方法呢?


我尝试执行以下操作,但收到评论中指定的警告:

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

我假设 va_start() 可以接受 (char *) 的原因是因为我在STDARG(3) 的手册页上看到的示例。如果我做错了,请随意完全重写该方法。

4

2 回答 2

15

我认为你想要的是这样的:

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

* 宏在stdarg.h va_函数(或者,在这种情况下,方法)采用可变数量的参数时使用,如“ ...”所指定。 va_start()用于查找可变数量参数的开始位置。因此,它需要知道函数/方法的最后一个参数(“”之前的那个...),以确定可变数量的参数从哪里开始。这是一个稍微简化的解释,因为幕后实际发生的事情是非常特定于 ABI/编译器的。最重要的一点是,to 的第二个参数va_start()始终是变量的名称'就在“ ...”'之前。

va_end()应该被“调用”(它实际上是一个宏,而不是一个函数)以获得最大的可移植性。再一次,这整个可变参数的事情是深奥的黑魔法。根据编译器和 ABI 的具体情况,va_end()可能根本不会做任何事情。另一方面,由于堆栈帧(如果有的话)不再正确设置为实际执行返回,因此未能使用va_end()可能会导致您的程序在到达语句时崩溃。return

于 2009-07-30T21:34:56.777 回答
8

你几乎明白了;只是几个调整:

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

那应该做你正在寻找的东西。

于 2009-07-30T21:30:25.880 回答