17

include/linux/typecheck.hLinux カーネル 4.16のファイルには、このコードが含まれています。

#define typecheck(type,x) \
({      type __dummy; \
        typeof(x) __dummy2; \
        (void)(&__dummy == &__dummy2); \
        1; \
}

xが parameter と同じタイプかどうかをチェックしますtype

しかし、私は次の行を理解できません:

 (void)(&__dummy == &__dummy2);

両方の変数の最初のアドレスを比較すると、どのように役立つでしょうか?

4

2 に答える 2

12

これは、2つのGCC拡張機能(式ステートメント({ ... })と)を使用しtypeof()ます。

  1. 展開の最初の行は、名前付き型の変数を宣言しますtype
  2. 展開の2行目は、変数または式と同じ型の変数を宣言していますx
  3. 3行目は、2つのポインターを比較します。これは、2つのダミー変数のタイプが一致する場合にのみ一致し、ポインターの不一致の警告(またはでコンパイルする場合はエラー)を生成します-Werror
  4. 最後の行(を含む1)は、式の値です—trueと同等です。

xしたがって、のタイプが指定されたタイプと同じでない場合は、コンパイルの警告/エラーが発生します。

コード例:

#include <stdio.h>

#define typecheck(type,x) \
({      type __dummy; \
        typeof(x) __dummy2; \
        (void)(&__dummy == &__dummy2); \
        1; \
})

int main(void)
{
    int x;
    if (typecheck(int, x))
        printf("int x OK\n");
    if (typecheck(double, x))
        printf("double x OK\n");
    return(0);
}

コンパイルメッセージ:

$ /usr/bin/gcc -O3 -g -std=gnu99 -Wall -Wextra xx.c -o xx  
xx.c: In function ‘main’:
xx.c:15: warning: comparison of distinct pointer types lacks a cast
$

を使用しなかったため-Werror、コードは「OK」をコンパイルしたことに注意してください。出力は次のとおりです。

int x OK
double x OK
于 2012-05-01T05:30:05.793 に答える
9

ポインターを互換性のない型と比較することは制約違反であり、コンパイラーが診断を発行する必要があります。6.5.9等式演算子を参照してください。

制約

次のいずれかが成立します。

  • 両方のオペランドは算術型です。
  • 両方のオペランドは、互換性のあるタイプの修飾バージョンまたは非修飾バージョンへのポインターです。
  • 一方のオペランドはオブジェクトまたは不完全な型へのポインターであり、もう一方は修飾または非修飾バージョンのvoidへのポインターです。また
  • 一方のオペランドはポインターで、もう一方はヌルポインター定数です。

および5.1.1.3診断:

動作が未定義または実装として明示的に指定されている場合でも、前処理の変換ユニットまたは変換ユニットに構文規則または制約の違反が含まれている場合、準拠する実装は少なくとも1つの診断メッセージ(実装定義の方法で識別される)を生成する必要があります-定義されています。他の状況では、診断メッセージを生成する必要はありません。

于 2012-05-01T05:31:38.743 に答える