Форум » C/C++ для начинающих (C/C++ for beginners) » Инкрементация или декрементация переменной,имеющий тип массива. » Ответить

Инкрементация или декрементация переменной,имеющий тип массива.

Сыроежка: Часто начинающие программисты задают вопрос о том, почему нельзя инкрементировать или декрементировать переменную, имеющую тип массива (смотрите, к примеру, вопрос на Stackoverflow C++ array variable increment and decrement) То есть почему, в частности, данная программа некорректна [pre2] #include <iostream> int main() { int a[] = { 1, 2, 3, 4, 5 }; std::cout << a++ << std::endl; return 0; } [/pre2] Часто ответы на этот вопрос содержат общие рассуждения, что такая операция для массивов не имеет смысла, и что массивы - это не указатели. Однако в представленной выше программе, строго говоря, имеет место попытка инкрементировать именно указатель. Точный ответ в соответствии со стандартом C++ (и стандартом C) заключается в следующем. Первое (C++17 Standard, 8.5.1.6 Increment and decrement) - постфиксный инкремент или декремент (как и аналогичные префиксные операции) требуют наличие изменяемой lvalue. [quote]1 The value of a postfix ++ expression is the value of its operand. [ Note: The value obtained is a copy of the original value — end note ] The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type other than cv bool, or a pointer to a complete object type. The value of the operand object is modified by adding 1 to it....[/quote] Второе (C++ 17 Standard, 7.2 Array-to-pointer conversion) - переменная, имеющая тип массива, в выражениях, за редким исключением неявно преобразуется во временный объект, который не является lvalue, и который имеет тип указателя на первый элемент массива. [quote]1 An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. The temporary materialization conversion (7.4) is applied. The result is a pointer to the first element of the array.[/quote] То есть, фактически, в этом выражении [pre2] a++[/pre2] имеет место не инкрементирование исходного массива, а попытка инкрементировать временный указатель, который указывает на первый элемент массива, но который при этом не является lvalue. Если же вместо временного указателя, в который неявно преобразуется переменная, имеющая тип массива, использовать lvalue, имеющего такой же тип указателя, то программа будет корректно компилироваться [pre2] #include <iostream> int main() { int a[] = { 1, 2, 3, 4, 5 }; int *p = a; std::cout << p++ << std::endl; return 0; }[/pre2] В этой демонстрационной программе переменная a, используемая в качестве инициализатора при объявления указателя p, также преобразуется во временный объект, который является указателем на первый элемент массива. Однако теперь это значение указателя сохраняется в переменной p, которая является не временным объектом, а lvalue. А потому к этой переменной p можно применить операцию инкремента.

Ответов - 0



полная версия страницы