Linux内核的类型检查宏如何工作?

lxg*_*eek 13 c linux linux-kernel

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

#define typecheck(type,x) \
({      type __dummy; \
        typeof(x) __dummy2; \
        (void)(&__dummy == &__dummy2); \
        1; \
}
Run Code Online (Sandbox Code Playgroud)

检查if x是否与参数的类型相同type.

但我无法理解这一行:

 (void)(&__dummy == &__dummy2);
Run Code Online (Sandbox Code Playgroud)

如何比较两个变量的第一个地址有帮助吗?

Jon*_*ler 10

这使用两个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);
}
Run Code Online (Sandbox Code Playgroud)

编译信息:

$ /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
$
Run Code Online (Sandbox Code Playgroud)

请注意,因为我没有使用-Werror,所以代码编译为'OK'.输出是:

int x OK
double x OK
Run Code Online (Sandbox Code Playgroud)


R..*_*R.. 7

比较具有不兼容类型的指针是违反约束并要求编译器发出诊断.见6.5.9平等算子:

约束

以下其中一项应持有:

  • 两个操作数都有算术类型;
  • 两个操作数都是指向兼容类型的限定或非限定版本的指针;
  • 一个操作数是指向对象或不完整类型的指针,另一个是指向void的限定或非限定版本的指针; 要么
  • 一个操作数是一个指针,另一个是空指针常量.

和5.1.1.3诊断:

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