Есть код:
float x=-8.92;
int y=5;
printf("%u\n", sizeof x+y);
printf("%u\n", sizeof (x+y));
Заключение:
9
4
Почему это происходит (результат 9)? Ведь это простые унарные операции.
sizeof x == 4
-> y == 5
-> 4 + 5 == 9
sizeof
скобки не нужны. Скобки необходимы только для типа данных, например. sizeof (int)
.
Пожалуйста, смотрите этот пост здесь о том, когда использовать скобки.
@ i486 sizeof
скобки не нужны. Скобки необходимы только для типа данных, например. sizeof (int)
Это означает, что вы всегда должны использовать их. Неважно, они делают ошибки, подобные тем, которые демонстрирует эта программа, невозможными.
касательно; float x=-8.92;
Буквальное: -8.92
объявляет значение double
, которое затем преобразуется в значение float
. Чтобы объявить значение float
, используйте: -8.92f
Обратите внимание на трейлинг f
относительно: printf("%u\n", sizeof x+y); printf("%u\n", sizeof (x+y));
sizeof
возвращает size_t
, который является unsigned long int
A u
не является допустимым спецификатором выходного формата для size_t
Предложите использовать: %zu
@AndrewHenle Скобки не могут помочь тому, кто пишет sizeof (x+y)
.
@ i486 Значение sizeof (x+y)
понятно. Какая помощь там нужна? Если это не то, что имел в виду программист, это не проблема с синтаксисом языка, и это не проблема замены x + y
на x / y
.
Это выражение
sizeof x+y
эквивалентно выражению
( sizeof x ) + y
Так как sizeof x
равно sizeof( float )
, то есть 4
, то результат исходного выражения равен 9
.
Оператор sizeof
является унарным оператором, а его операнд, в свою очередь, является унарным выражением. То есть оператор, в частности, определяется как
sizeof unary-expression
x + y
является аддитивным выражением, а переменная x
в качестве первичного выражения, в свою очередь, является унарным выражением. Таким образом, оператор применяется к переменной x.
С другой стороны, выражение ( x + y )
является первичным выражением и в силу обычных арифметических преобразований имеет тип float
. Таким образом, в этом случае, когда выражение записывается как sizeof( x + Y )
, оператор sizeof
снова применяется к первичному (унарному) выражению и эквивалентен sizeof( float )
.
Обратите внимание, что вместо спецификатора преобразования %u
в вызовах %zu
следует использовать спецификатор преобразования printf
. Типом обоих выражений sizeof x + y
и sizeof( x + y )
является size_t
, который является типом, определенным реализацией, который обычно является псевдонимом для типа unsigned long
. Для типа size_t
определен спецификатор преобразования zu
, который вы должны использовать. В противном случае вызов printf
с неправильным спецификатором преобразования может привести к неопределенному поведению.
Спасибо за подробный ответ. Не могли бы вы подсказать, почему следует использовать «%zu» вместо «%u»?
@Thepersonwiththequestion Смотрите мой приложенный ответ.
Оператор sizeof
имеет более высокий приоритет, чем оператор двоичного сложения +
. Итак, это:
sizeof x+y
Разбирает как:
(sizeof x)+y
Таким образом, в первом выражении вы получаете размер float
, который в вашей системе равен 4, и добавляете к нему значение 5, в результате чего получается 9. Во втором выражении подвыражение x+y
имеет тип float
из-за обычных арифметических преобразований, поэтому результат равен 4, что и напечатано.
Спасибо. Я действительно забыл о приоритете унарных операций.
sizeof x+y
совпадает с (sizeof x) + y
, то есть sizeof
имеет более высокий приоритет, чем +
.
Ваш компилятор должен был предупредить вас о несоответствии между строкой формата printf()
(%u
) и аргументом (size_t
, int
или другим) — если вы используете GCC, вы должны добавить -Wall -Wextra
в команду компиляции.
Обязательно изучу "- Wall-Wextra". Спасибо за совет .
Фактический тип аргумента — size_t в обоих вызовах, правильный спецификатор формата — %zu
.
@zwol, int
+ size_t
не обязательно size_t
. Но да, я получил x
и y
неправильно - теперь исправлено.
@TobySpeight Думаю, технически size_t
может быть меньше, чем int
(минимальный максимум для size_t
равен 65536, как и unsigned short
, и unsigned int
), но мне это кажется действительно странным ABI. Вы знаете настоящий ABI, который делает это?
О да, это звучит очень маловероятно, соглашусь. Нет, я не знаю о таких системах (но я, как правило, работаю с обычными рабочими станциями Unix, так что вряд ли буду). Кроме того, я изо всех сил пытаюсь запомнить общий тип значений со знаком и без знака для арифметики. В любом случае, спасибо, что указали, что я забыл, какая переменная была float
.
Результат «sizeof» зависит от расположения скобок. Почему?
Потому что «скобки» переопределяют приоритеты операторов.
sizeof x+y = sizeof(x)+y = 4+5 =9