Почему этот код компилируется?
_Static uint32_t my_arr[2];
_Static_assert(sizeof(my_arr) == 8, "");
_Static_assert(sizeof(my_arr[0]) == 4, "");
_Static_assert(sizeof(my_arr)[0] == 4, "");
Первые 2 утверждения, очевидно, верны, но я ожидал, что последняя строка не удастся, поскольку я понимаю, что она sizeof()
должна оцениваться как целочисленный литерал, который нельзя рассматривать как массив. Другими словами, произойдет сбой так же, как и в следующей строке:
_Static_assert(4[0] == 4, "");
Интересно, что следующее действительно не компилируется (что должно делать то же самое, не так ли?):
_Static_assert(*sizeof(my_arr) == 4, "");
ошибка: недопустимый аргумент типа унарного '*' (есть 'long unsigned int') _Static_assert (* sizeof (my_arr) == 4, "");
Если это важно, я использую gcc 5.3.0
( sizeof( my_arr ) )[ 0 ]
не так.Ответы:
sizeof
это не функция. Это унарный оператор, например!
или~
.sizeof(my_arr)[0]
анализирует какsizeof (my_arr)[0]
, что простоsizeof my_arr[0]
с избыточными круглыми скобками.Это похоже на
!(my_arr)[0]
синтаксический анализ как!(my_arr[0])
.В общем, постфиксные операторы имеют более высокий приоритет, чем префиксные операторы в C.
sizeof *a[i]++
анализируются какsizeof (*((a[i])++))
( сначала применяются постфиксные операторы[]
и , затем префиксные операторы и ).++
a
*
sizeof
(Это версия выражения
sizeof
. Существует также версия типа, которая принимает имя типа в скобках:.sizeof (TYPE)
В этом случае скобки потребуются и являются частьюsizeof
синтаксиса.)источник
sizeof
чтобы стать унарным оператором."... parses as sizeof (my_arr[0])"
? Простое добавление пробела на самом деле ничего не меняет.sizeof((my_array)[0])
вместо этогоsizeof
имеет две «версии»:sizeof(type name)
иsizeof expression
. Первый требует наличия пары()
аргументов. Но последний - тот, у которого есть выражение в качестве аргумента - не имеет()
вокруг себя аргумента. Все, что()
вы используете в аргументе, рассматривается как часть выражения аргумента, а не как часть самогоsizeof
синтаксиса.Поскольку
my_arr
компилятор известен как имя объекта, а не как имя типа, вашsizeof(my_arr)[0]
фактически рассматривается компилятором какsizeof
примененный к выражению:,sizeof (my_arr)[0]
где(my_arr)[0]
- выражение аргумента.()
Окружающее имя массива является чисто излишним. Все выражение интерпретируется какsizeof my_arr[0]
. Это эквивалентно предыдущемуsizeof(my_arr[0])
.(Это означает, BTW, что ваш предыдущий
sizeof(my_arr[0])
также содержит пару лишних()
.)Это довольно распространенное заблуждение, что
sizeof
синтаксис каким-то образом требует наличия пары()
аргументов. Это заблуждение вводит в заблуждение интуицию людей при интерпретации таких выражений, какsizeof(my_arr)[0]
.источник
int
не является допустимым выражением, поэтому вы не можете использовать вторая форма с ней.[]
имеют более высокий приоритет, чемsizeof
. Такsizeof(my_arr)[0]
же, какsizeof((my_arr)[0])
.Вот ссылка на таблицу приоритетов.
источник
Вы используете версию
sizeof
оператора, которая принимает выражение в качестве параметра. В отличие от того, что принимает тип, здесь не нужны скобки. Следовательно, операнд простой(my_arr)[0]
, круглые скобки лишние.источник