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/コンパイラ固有であるため、これはやや単純化された説明です。最も重要な点は、 の 2 番目の引数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 に答える