sizeof(Sales_data); //
//
sizeof data; //
sizeof p; //
sizeof *p; //
//
sizeof data.revenue; //
sizeof Sales_data::revenue; // альтернативный способ получения
//
Наиболее интересен пример sizeof *p
. Во-первых, поскольку оператор sizeof
имеет правосторонний порядок и тот же приоритет, что и оператор *
, это выражение группируется справа налево. Таким образом, оно эквивалентно выражению sizeof(*p)
. Во-вторых, поскольку оператор sizeof
не выполняет свой операнд, не имеет значения, допустим ли указатель p
(т.е. инициализирован ли он) (см. раздел 2.3.2). Обращения к значению недопустимого указателя оператор sizeof
не осуществляет, и указатель фактически не используется, поэтому он безопасен. Ему и не нужно обращаться к значению указателя, чтобы выяснить, какой тип он возвратит.
sizeof
не обязан выбирать член класса, чтобы узнать его размер.
Результат применения оператора sizeof
частично зависит от типа, к которому он применен.
• Если это тип char
или выражения, результат которого имеет тип char
, то это гарантированно будет 1
.
• Если это ссылка, то возвращает размер типа объекта, на который она ссылается.
• Если это указатель, то возвращается размер, необходимый для хранения указателя.
• Если это обращение к значению указателя, то возвращается размер типа объекта, на который он указывает, вне зависимости от его допустимости.
• Если это массив, то возвращается размер всего массива. Это эквивалентно получению размера элемента массива и его умножению на количество элементов. Обратите внимание, что оператор sizeof
не преобразует массив в указатель.
• Если это строка или вектор, то возвращается размер только фиксированной части этих типов; но не размер, используемый элементами объекта.
Поскольку оператор sizeof
возвращает размер всего массива, разделив размер массива на размер элемента, можно определить количество элементов в массиве:
//
constexpr size_t sz = sizeof (ia)/sizeof(*ia);
int arr2[sz]; //
//
Так как оператор sizeof
возвращает константное выражение, его результат можно использовать в выражении для определения размерности массива.
Упражнение 4.28. Напишите программу для вывода размера каждого из встроенных типов.
Упражнение 4.29. Предскажите вывод следующего кода и объясните свое рассуждение. Напишите и выполните соответствующую программу. Совпадает ли вывод с ожиданиями? Если нет, то объясните почему.
int x[10]; int *p = x;
cout << sizeof(x)/sizeof(*x) << endl;
cout << sizeof(p)/sizeof(*p) << endl;
Упражнение 4.30. Используя таблицу из раздела 4.12, расставьте скобки в следующих выражениях так, чтобы продемонстрировать порядок его обработки:
(a) sizeof x + y (b) sizeof p->mem[i]
(с) sizeof а < b (d) sizeof f()
4.10. Оператор запятая
,
) (comma operator) получает два операнда, обрабатываемых слева направо. Подобно операторам логического AND и OR, а также условному оператору, оператор запятая гарантирует порядок обработки своих операндов.
Левое выражение обрабатывается, а его результат отбрасывается. Результат выражения запятая — это значение правого выражения. Результат является l-значением, если правый операнд — l-значение.
Оператор запятая нередко используется в цикле for
:
vector
//
for (vector
ix != ivec.size(); ++ix, --cnt)