2011-10-03 16 views
7

gnuのCのドキュメントには、関数に__attribute__((sentinel))がある場合、その関数の最後の引数としてNULLが必要であることが記載されています。カスタムセンチネル値を持つvariadic関数を作成するにはどうすればよいですか?

引数リストを終了するマーカーとして他の値を使用することはできますか?

+1

このような関数を作成する限り、明らかにその関数を作成することができます。私は、引数が任意の可変引数スキームに対して正しいことを確認するためのGNU拡張について知らない。彼らは、コンパイラが正しいかどうかをチェックできるように、引数の数を引数としてマークする属性さえも持っていません。 –

答えて

3

引数リストから取得することが分かっていれば、引数リストの終わりをマークする任意の値を使用できます。コンパイラは通常、関数が呼び出されたときに選択した値が実際に渡されるかどうかをチェックしないため、注意が必要です。

本質的に、通常の方法で変数の関数を作成するだけで、関数内では、あなたのマニアと一致するものを読むときに引数の読み込みを停止します。特に何もする必要はありませんが、読み込む引数。例えば

#include <stdarg.h> 

/* Count arguments up to the number 5 */ 
int countArgsTilFive(int first, ...) 
{ 
    int res = 1; 
    va_list ap; 
    if (first == 5) return 0; 
    va_start(ap,first); 
    while (va_arg(ap,int) != 5) res++; 
    va_end(ap); 
    return res; 
} 

... 5前に発生するすべての引数をカウントします。あなたがそれをリストのどこかで 5に渡さないと、悪いことが起きる可能性があります。または、 intではない引数を渡すと、悪いことが起こる可能性があります。これは、Appleが便利 NS_REQUIRES_NIL_TERMINATIONを定義する方法(の編集されたダウンバージョン)です

/* Count arguments, excluding the first, until the first occurs again */ 
int countPtrs(void *sentinel, ...) 
{ 
    int res = 0; 
    va_list ap; 
    va_start(ap,sentinel); 
    while (va_arg(ap,void *) != sentinel) res++; 
    va_end(ap); 
    return res; 
} 
+1

GCCの '__attribute __((sentinel))'では、引数リストが指定された値で終了することをコンパイラが確認できます。それが許す唯一の値は 'NULL'です。コンパイラが検証するための別の値を選ぶことはできません。 –

+1

任意のセンチネル値に対して '__attribute __((sentinel)) 'のようなものがあるかどうかを知りたければ、その答えは役に立たないが、' __attribute __((sentinel)) 'に関する印象が残っていればNULL以外のセンチネルはまったく使用できないので、それをクリアする必要があります。 – Dmitri

0

:センチネルノードが最初のように、そして再び最後の、引数として渡されたポインタを、と

もう一つの例いくつかの方法ではnilセンチネルを必要とするため、プリコンパイルチェック、すなわち...

+ (NSArray*)arrayWithRects:(NSR)rect,...NS_REQUIRES_NIL_TERMINATION;

#if !defined(NS_REQUIRES_NIL_TERMINATION) 
#if defined(__APPLE_CC__) && (__APPLE_CC__ >= 5549) 
    #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel(0,1))) 
#else 
    #define NS_REQUIRES_NIL_TERMINATION __attribute__((sentinel)) 
#endif 
#endif 

何differencかなりわかりませんeは2つのコンパイラ指令の間にありますが、私はこのコンストラクトを "他の"、 "カスタム"のセンチネルと併用することができると仮定しています。私はNSNotFound - XX_REQUIRES_NSNOTFOUND_TERMINATIONかそれに類似すると思いますか?

関連する問題