I am new to the Linux kernel. I am reading the file ioctl.h
, there I encountered a macro
_IOC_TYPECHECK(t)
, which looks like this:
It means the same as all other uses of sizeof
. It computes the size of the expression.
In this particular case, I suspect that the check is intended to ensure some property of t
(which should be a type name, not a variable) which I don't know from the context ... Perhaps that it's possible to treat it as a pointer (needed for the array indexing) which would rule out some types. The comment next to the macro says /* provoke compile error for invalid uses of size argument */
which seems to support this theory.
Note that sizeof
is an operator, not a function. The parenthesis are not needed, except when you want to compute the size of a type directly, and then they're part of the expression (it's a cast expression). So this could be written sizeof t == sizeof t[1] && ...
, or maybe (sizeof t == sizeof t[1])
for clarity.
This is a very good style to use, since it "locks" the size being computed to the proper array, instead of repeating the type of t
. So, if the type were to change, the expression would automatically adapt and still compute the right thing.
Many C programmers seem to prefer having parenthesis around the argument to sizeof
in all cases, for some reason.
This is used to check the validity of the third parameter to the _IOR
/_IOW
/_IOWR
macros, which is supposed to be a type. It checks that the parameter is actually a type (and not a variable or a number), and causes a compiler or linker error otherwise.
If t
is a type, then t[1]
is the type "an array of 1 t
". This type has the same size as t
, and therefore sizeof(t) == sizeof(t[1])
is true.
If t
is a number, sizeof(t)
will fail to compile.
If t
is a simple (non-array) variable, then t[1]
will cause a compiler error.
If t
is an array variable, sizeof(t) == sizeof(t[1])
will be false, and a linker error will be caused (because __invalid_size_argument_for_IOC
is not defined).
The expression sizeof(t) < (1 << _IOC_SIZEBITS)
checks that the size of the type t
does not exceed the maximum allowed for ioctl
, and causes the same linker error otherwise.
There are still some invalid cases which will not be caught by this macro - for example, when t
is a pointer to a pointer.