2016-01-01 5 views
5

ロックに失敗した場合に備えて、以下のマクロを作成してミューテックスをロックし、(このマクロが呼び出される関数から)返すようにしました。現在、私は2つのマクロに絞っています - タイプにかかわらず値を返す関数から返るものと、何も返さない関数から返るもの(すなわち、void)です。何も含まないさまざまな型の値を返す単一のマクロ関数を提供する方法はありますか?

(下記)マクロを超えたコードは、単に例示のためのものであり、マクロがで使用される実際の生産コードとはほとんど関係がない。

#define MUTEX_LOCK()\ 
    {\ 
     if (pthread_mutex_lock(&mutex) != 0)\ 
     {\ 
      printf("Failed to lock mutex.\n");\ 
      return;\ 
     }\ 
    } 
#define MUTEX_LOCK_RVAL(err_val)\ 
    {\ 
     if (pthread_mutex_lock(&mutex) != 0)\ 
     {\ 
      printf("Failed to lock mutex.\n");\ 
      return err_val;\ 
     }\ 
    } 

void vfunc() 
{ 
    printf("\nIn vfunc()\n"); 
    MUTEX_LOCK(); 
    printf("\nOut of vfunc()\n"); 
} 

UINT16 uint16func() 
{ 
    printf("\nIn uint16func()\n"); 
    MUTEX_LOCK_RVAL(0); 
    printf("\nOut of uint16func()\n"); 

    return 9; 
} 

CHAR* errstr = "Hoo boy!"; 
CHAR* strfunc() 
{ 
    printf("\nIn strfunc()\n"); 
    MUTEX_LOCK_RVAL(errstr); 
    printf("\nOut of strfunc()\n"); 

    return NULL; 
} 

削減する方法はありますこれらのマクロは、値を返す関数で使用できる単一のマクロに加えて、voidと同様に使用できます。

+4

returnを含む関数型マクロ...これは本当に厄介です。それを忘れて、適切なロック機能を使って 'if(!my_lock())return​​;'を呼び出しサイトで使用してください。 – Mat

+1

[variadic macros](https://en.wikipedia.org/wiki/Variadic_macro)がありますが、警告があります。そして、あなたのコードの他の読者(そして1年程度であなたを含む他の人たち)には本当に混乱します。 –

+0

@JoachimPileborg呼び出しが混乱するか、マクロ定義のみが必要ですか?後者のみの場合、賢明なコメントがあればそれを解決すべきでしょうか? –

答えて

4

それはANSI互換性を持たせるために、私はリターンでマクロや他の単純なシンボル定義nullに評価され、nullであることがはっきりと示されています。 すなわち:

#define VOID_RET //This nulls the return value 
#define MUTEX_LOCK(err_val)\ 
    {\ 
     if (pthread_mutex_lock(&mutex) != 0)\ 
     {\ 
      printf("Failed to lock mutex.\n");\ 
      return err_val;\ 
     }\ 
    } 
void *mutex = NULL; 
void vfunc(void) 
{ 
    printf("\nIn vfunc()\n"); 
    MUTEX_LOCK(VOID_RET); 
    printf("\nOut of vfunc()\n"); 
} 
UINT16 uint16func(void) 
{ 
    printf("\nIn uint16func()\n"); 
    MUTEX_LOCK(0); 
    printf("\nOut of uint16func()\n"); 

    return 9; 
} 
CHAR* errstr = "Hoo boy!"; 
CHAR* strfunc(void) 
{ 
    printf("\nIn strfunc()\n"); 
    MUTEX_LOCK(errstr); 
    printf("\nOut of strfunc()\n"); 

    return NULL; 
} 

私はC11とC99の下にこのコードをテストしました。

+0

これは厳密なC90でも動作します(少なくともGCCでは)。 –

+0

とにかく、これは私の解決策よりもはるかに良いです。 – Rabbid76

2

ドキュメントからわかるように、引数を必要とするマクロ関数に引数をまったく渡す義務がないため、引数を取らないマクロ関数を削除できます。
GNU GCC documentationより:

マクロ引数は空のままにできます。これは プリプロセッサ[...]複数の引数については


にエラーではなく、これは興味深いです:

あなたは完全に引数を除外することはできません。マクロが2つの引数をとる場合は、引数リストの最上位にカンマが1つだけある必要があります。与えられたこれらの例では

min(, b)  ==> (( ) < (b) ? ( ) : (b)) 
min(a,)  ==> ((a ) < () ? (a ) : ()) 
min(,)   ==> (( ) < () ? ( ) : ()) 
min((,),)  ==> (((,)) < () ? ((,)) : ()) 
+1

私はこれを試しましたが、これは有効なansi Cではありません(** - pedanticと-Werror **フラグでコンパイルします)。エラーが出ます*空のマクロ引数はISO C90とISO C++ 98 *で定義されていません。 –

+0

@ work.binなぜこれらの古い基準に縛られているのか教えてください。少なくともC99は、今日のIMOのデフォルトでなければなりません。 – Downvoter

+0

お望みです!しかし、C99をサポートするコンパイラはあまり多くありません。移植性が懸念される場合は、C90に限定されます。 –

2

私は想像することができる唯一のソリューションはこれです:

#define MUTEX_LOCK(err_val)\ 
{\ 
    {\ 
     if (pthread_mutex_lock(&mutex) != 0)\ 
     {\ 
      printf("Failed to lock mutex.\n");\ 
      return err_val;\ 
     }\ 
    }\ 
} 

int test_int() 
{ 
    MUTEX_LOCK(1); 

    return 0; 
} 

void test_void() 
{ 
    MUTEX_LOCK(;); 

    return; 
} 
+0

特に優雅ではなく、賢い。これは私の質問に答えますが、私がこれを使用するかどうかはわかりません。 –

+0

@ work.bin私はあなたに完全に同意する、それは醜いです。 – Rabbid76

関連する問題