2013-02-18 4 views
8

Я новичок в ядре Linux. Я читаю файл ioctl.h, там я столкнулся с макро _IOC_TYPECHECK(t), который выглядит следующим образом:Что означает sizeof (int [1])?

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

Можете ли вы объяснить мне этот код? В этом коде, что означает sizeof(t[1])?

ответ

7

Это используется, чтобы проверить действительность третьего параметра на макросах _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 является указателем на указатель.

+0

«Если' t' является переменной массива, 'sizeof (t) == sizeof (t [1])' будет false ", это действительно всегда верно? –

+0

@AndreasGrapentin: Не для массива одного элемента, но тогда вы можете получить предупреждение компилятора для индексации массива за пределами границ. – interjay

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.

+1

't' здесь должен быть тип, а не переменная. Это третий параметр для макросов [_IOR] (http://h30097.www3.hp.com/docs/dev_doc/DOCUMENTATION/HTML/DDK_R2/DOCS/HTML/MAN/MAN9/0028___R.HTM)/_IOW/_IOWR. – interjay

+0

Я не знал, что параметры 'sizeof' были необязательными, за исключением типа; или что они являются технически отлитыми в этом случае. +1 только для этого! – Chowlett

+1

", а затем они являются частью выражения". Я не уверен, что понимаю, что вы имеете в виду здесь. Идентификатор типа (например, 'int') не обязательно должен иметь круглые скобки и не является выражением, но скобки требуются в' sizeof (int) ', потому что это правила грамматики ... или у вас что-то другое? Кроме того, это тоже не литье. –

Смежные вопросы