операнды для оператора sizeof - PullRequest
0 голосов
/ 31 января 2019

Я понял, что результат

int nData = 10;
printf("%d", sizeof(nData + 2.0));

равен "8"

, почему каждый результат

int nData = 10;
printf("%d", sizeof(nData = 2.0));
printf("%d", sizeof(nData += 2.0));

не 8, а 4?Почему nData не может быть 12.0 или 12 sizeof(nData += 2.0)?

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Поскольку 2.0 является константой типа double, выражение nData + 2.0 имеет тип double в соответствии с "обычными арифметическими преобразованиями", указанными в разделе 6.3.1.8 стандарта C:

Во-первых, если соответствующий действительный тип одного из операндов long long, другой операнд преобразуется без изменения в область типов в тип, соответствующий действительный тип которого long long.

В противном случае,если соответствующий действительный тип одного из операндов является двойным, другой операнд преобразуется без изменения домена типа в тип, соответствующий действительный тип которого является двойным

Так что sizeof оценивается какразмер double.

В случае nData = 2.0 и nData += 2.0 каждое выражение имеет тип int, так как это тип левой части присваивания.Таким образом, sizeof оценивается как размер int.

Кроме того, операнд оператора sizeof оценивается для его типа только во время времени компиляции .Это означает, что любое назначение или приращение не оцениваются во время выполнения.Итак, во втором примере nData будет по-прежнему иметь значение 10 после двух строк, которые используют sizeof.Единственный раз, когда операнд sizeof вычисляется во время выполнения, это если операнд является массивом переменной длины.

0 голосов
/ 31 января 2019

Почему nData не может быть 12.0 или 12 с sizeof(nData += 2.0)?

Ну, sizeof является компиляторомоператор времени , и он работает с типом данных, а не со значением.

Другими словами, за исключением случаев, когда аргумент является VLA , операнд sizeof не являетсяоцененный.

Цитирование C11, глава §6.5.3.4

Оператор sizeof возвращает размер (в байтах) своего операнда, который может быть выражением илиимя типа в скобках.Размер определяется по типу операнда.Если тип операнда является типом массива переменной длины, операнд оценивается;в противном случае, операнд не вычисляется, и результатом является целочисленная константа.

Так что, в вашем случае,

  printf("%d", sizeof(nData + 2.0));   // data == int, 2.0 == double

совпадает с

 printf("%d", sizeof(double));  //  as the resulting "type" of the addition, 
                                //   'int + double' would be  'double'

, который должен быть лучше

 printf("%zu", sizeof(double));   //not %d

, поскольку sizeof приводит к типу size_t.

Также относительно 2.0 типа double из главы §6.4.4.2

Плавающая константа имеет значимую часть, за которой может следовать часть экспоненты и суффикс, указывающий ее тип.Компоненты значимой части могут включать в себя последовательность цифр, представляющую часть целого числа, за которой следует точка (.), За которой следует последовательность цифр, представляющая часть дроби.[...]

и

Нефиксированная плавающая константа имеет тип double.[...]

Таким образом, постоянное значение типа 2.0 имеет тип double.

...