Jhony depp
Jhony depp

Reputation: 93

What does sizeof(int[1]) mean?

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:

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

Can you explain me this code? In this code, what does sizeof(t[1]) mean?

Upvotes: 9

Views: 1037

Answers (2)

interjay
interjay

Reputation: 110108

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.

Upvotes: 8

unwind
unwind

Reputation: 399813

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.

Upvotes: 3

Related Questions