Оцениваются операнды sizeof?

AFAIK sizeof не оценивает свои операнды на С++.

например.

int x = 0;
sizeof(x += 1); // value of x is not changed

Но что это значит?

int arr[5];
sizeof(arr+0); // here array is converted to pointer

Почему здесь применяется арифметика в массиве?

(§ 5.3.3/4) Значение lvalue-to-rvalue (4.1), массив-указатель (4.2) и Стандартные преобразования по функциям-к-указателю (4.3) не применяются к операнд sizeof.

Ответ 1

Оператор sizeof() вычисляется во время компиляции. Выражения НЕ. Это тип выражения, которое вычисляется (во время компиляции), а затем используется sizeof().

Итак, в первом:

sizeof( x += 1);

Тип x - int. Результатом оператора + = остается int. Поэтому sizeof() по-прежнему является размером int.

В этом:

sizeof(arr+0);

Здесь arr - массив и вернет размер массива (если он используется сам по себе). Но оператор + приводит к распаду массива в указатель. Результатом оператора + для массива и целого является указатель. Таким образом, оператор sizeof() вернет размер указателя.

(п. 5.3.3/4) Стандартные преобразования lvalue-to-rvalue (4.1), array-to-pointer (4.2) и стандартные для-указателя (4.3) не применяются к операнду sizeof.

Это означает, что:

std::cout << sizeof(arr);
       // would print sizeof(int)* 5 (because there is no conversion)
       // if sizeof() had behaved like a normal function there
       // would have been a conversion but as you pointed out that
       // does not apply.

Но здесь:

std::cout << sizeof(arr + 5);
       // prints the sizeof(int*) because the result of the expression
       // is a pointer type (int*)

В качестве примечания:

Вот почему

int x[0];
int const xSize = sizeof(x)/sizeof(x[0]);

// This works correctly even though x[0] is technically
// not valid if used in a real expression (but is valid here).

Ответ 2

Это не так. В арифметическом выражении имена массивов распадаются на указатели. Это ничего не говорит о выполнении самого расчета. Тип + выводится из типов его операндов, в данном случае - указателя и целого числа, что дает тот же результат, что и sizeof(int*).

Ответ 3

Я мало знаю об этом, но если, как вы говорите, sizeof не оценивает его операнд, тогда он должен просто полагаться на тип используемого выражения. Поэтому я бы предположил, что arr сам по себе имеет свой тип arr+0, и поэтому он был использован.