On-line: гостей 0. Всего: 0 [подробнее..]
Программисты всех стран, объединяйтесь!

АвторСообщение



ссылка на сообщение  Отправлено: 26.08.18 16:38. Заголовок: Инкрементация или декрементация переменной,имеющий тип массива.


Часто начинающие программисты задают вопрос о том, почему нельзя инкрементировать или декрементировать переменную, имеющую тип массива (смотрите, к примеру, вопрос на Stackoverflow C++ array variable increment and decrement)

То есть почему, в частности, данная программа некорректна
 
#include <iostream>

int main()
{
int a[] = { 1, 2, 3, 4, 5 };

std::cout << a++ << std::endl;

return 0;
}


Часто ответы на этот вопрос содержат общие рассуждения, что такая операция для массивов не имеет смысла, и что массивы - это не указатели.

Однако в представленной выше программе, строго говоря, имеет место попытка инкрементировать именно указатель.

Точный ответ в соответствии со стандартом C++ (и стандартом C) заключается в следующем.

Первое (C++17 Standard, 8.5.1.6 Increment and decrement) - постфиксный инкремент или декремент (как и аналогичные префиксные операции) требуют наличие изменяемой lvalue.

 цитата:
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....



Второе (C++ 17 Standard, 7.2 Array-to-pointer conversion) - переменная, имеющая тип массива, в выражениях, за редким исключением неявно преобразуется во временный объект, который не является lvalue, и который имеет тип указателя на первый элемент массива.


 цитата:
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.



То есть, фактически, в этом выражении

 
a++

имеет место не инкрементирование исходного массива, а попытка инкрементировать временный указатель, который указывает на первый элемент массива, но который при этом не является lvalue.

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

 
#include <iostream>

int main()
{
int a[] = { 1, 2, 3, 4, 5 };
int *p = a;

std::cout << p++ << std::endl;

return 0;
}


В этой демонстрационной программе переменная a, используемая в качестве инициализатора при объявления указателя p, также преобразуется во временный объект, который является указателем на первый элемент массива. Однако теперь это значение указателя сохраняется в переменной p, которая является не временным объектом, а lvalue. А потому к этой переменной p можно применить операцию инкремента.

Спасибо: 0 
ПрофильЦитата Ответить
Новых ответов нет


Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 31
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет