На самом деле довольно много причин, почему второй не работает. Я уверен, что вы это знаете, но я просто повторю: массив не является указателем. Массивы конвертируются только в указатели. Это происходит автоматически, и это происходит «очень часто», но массивы и указатели по-прежнему являются разными типами. С точки зрения языка, вы просто не можете присвоить массиву (значения l типа массива не являются «изменяемыми значениями l»), и, в частности, «скрытое» присваивание string = string + 1
в string++
не работает. Вы можете, конечно, назначить переменную указателя. По этой причине в стандарте C ++
определено для работы только с числовыми («действительными») и указательными типами, а это означает, что вам нельзя указывать массив.
В терминахиз почему правила таковы, один ход мыслей начинается с того, что он замечает, что тип массива является «полным» только тогда, когда он имеет размер, т.е. если у вас есть переменная типа массива, его размерчасть своего типа. Попытка изменить string
с помощью арифметики, как вы делаете здесь, потребует изменения типа string
, потому что размер изменится, но это не разрешено в C. (Обратите внимание, что char string[];
является недопустимым объявлением, потому что ононе указывает размер; когда вы добавили инициализатор, вы сказали C выводить из него размер (3
).) В версии указателя pstring
- это char*
, как и pstring + 1
, поэтомунет проблем. В версии массива вы должны иметь char string[3]
перед циклом и char string[1]
после. Хуже того, окончательный размер string
будет зависеть от данных в нем, поэтому невозможно будет предсказать его с точки зрения языка. Лучше не открывать, что может червей, не так ли?
Идея увеличения string
также не работает, потому что в C "объект массива" на 1021 * больше , чем "связка смежных"элементы». Когда вы объявляете string
, да, вы создаете кучу char
объектов, которые являются смежными в памяти, но вы также «благословляете» (это не технический термин, если вы не используете Perl :)) эту память вбудучи char[3]
объектом. Вероятно, с точки зрения реальной машины это «благословение» на самом деле ничего не значит и не означает, но с точки зрения абстрактной машины, на которой работают программы на Си, есть разница. В частности, нет ни объекта char[2]
, расположенного по адресу памяти string + 1
, ни char[1]
в string + 2
. Таким образом, если бы вы увеличили string
, , не было бы массива для string
, на который можно было бы ссылаться больше.
Я полагаю, вы можете свести все это к интуиции, что массивна самом деле просто "куча переменных". То есть, когда вы объявили char string[3];
, должно появиться ощущение, что вы char string_0, string_1, string_2;
. Это как если бы у вас было struct { int x; char y; } test;
- это похоже на запись int test_x; char test_y;
. «Увеличение группы переменных» совершенно бессмысленно, поэтому, конечно, string++
и test++
запрещены. С string
у вас есть возможность создать char *pstring
, такой, что pstring = &string_0
, pstring + 1 = &string_1
, pstring + 2 = &string_2
, но это не меняет того факта, что выполнение арифметики на самом string
(особенно деструктивно увеличивающемся)это) не имеет смысла.