17

Linux 内核 4.16的文件include/linux/typecheck.h包含此代码。

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

它检查是否x与参数类型相同type

但我无法理解这条线:

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

比较两个变量的第一个地址有什么帮助?

4

2 回答 2

12

这使用了两个 GCC 扩展——表达式语句({ ... })typeof().

  1. 展开的第一行声明了一个命名类型的变量type
  2. 扩展的第二行声明了一个与变量或表达式相同类型的变量x
  3. 第三行比较两个指针,只有当两个虚拟变量的类型匹配时才会匹配,产生指针不匹配警告(如果用 编译则错误-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 诊断:

如果预处理翻译单元或翻译单元包含违反任何语法规则或约束的行为,则符合要求的实现应产生至少一个诊断消息(以实现定义的方式标识),即使该行为也明确指定为未定义或实现-定义。在其他情况下不需要生成诊断消息。

于 2012-05-01T05:31:38.743 回答