9

我是 Linux 内核的新手。我正在阅读文件ioctl.h,在那里我遇到了一个宏 _IOC_TYPECHECK(t),它看起来像这样:

#define _IOC_TYPECHECK(t) \
        ((sizeof(t) == sizeof(t[1]) && \
          sizeof(t) < (1 << _IOC_SIZEBITS)) ? \
          sizeof(t) : __invalid_size_argument_for_IOC)

你能解释一下这段代码吗?在这段代码中,是什么sizeof(t[1])意思?

4

2 回答 2

8

这是用来检查//宏的第三个参数的有效性_IOR_IOW_IOWR应该是一个类型。它检查参数是否实际上是一种类型(而不是变量或数字),否则会导致编译器或链接器错误。

  • 如果t是类型,则t[1]类型为“1 的数组t”。此类型与 具有相同的大小t,因此sizeof(t) == sizeof(t[1])是正确的。

  • 如果t是数字,sizeof(t)将无法编译。

  • 如果t是一个简单的(非数组)变量,那么t[1]将导致编译器错误。

  • 如果t是数组变量,则为sizeof(t) == sizeof(t[1])假,会导致链接器错误(因为__invalid_size_argument_for_IOC未定义)。

该表达式sizeof(t) < (1 << _IOC_SIZEBITS)检查类型的大小t是否不超过允许的最大值ioctl,否则会导致相同的链接器错误。

仍然有一些无效的情况不会被这个宏捕获 - 例如,t指向指针的指针。

于 2013-02-18T10:51:26.480 回答
3

它的含义与 的所有其他用途相同sizeof。它计算表达式的大小。

在这种特殊情况下,我怀疑检查是为了确保t我从上下文中不知道的某些属性(应该是类型名称,而不是变量)......也许可以将其视为将排除某些类型的指针(需要用于数组索引)。宏旁边的评论说/* provoke compile error for invalid uses of size argument */这似乎支持这一理论。

请注意,这sizeof是一个运算符,而不是一个函数。不需要括号,除非您想直接计算类型的大小,然后它们是表达式的一部分(它是一个强制转换表达式)。所以这可以写出来sizeof t == sizeof t[1] && ...,或者(sizeof t == sizeof t[1])为了清楚起见。

这是一种非常好的使用方式,因为它将计算的大小“锁定”到正确的数组,而不是重复t. 所以,如果类型发生变化,表达式会自动适应并仍然计算正确的东西。

sizeof出于某种原因,许多 C 程序员似乎更喜欢在所有情况下都在参数周围加上括号。

于 2013-02-18T10:38:58.630 回答