Другие ответы правильно объясняют, почему sizeof (*str) == 1
, но они не решают вашу понятную путаницу.
Массивы C в некотором смысле являются гражданами второго сорта. Объекты массива - это реальные объекты, такие как объекты любого другого типа (целое число, структура и т. Д.), Но язык предоставляет очень мало операций, которые работают непосредственно с массивами.
Вместо этого, объектами массива обычно манипулируют с помощью указателей наих элементы.
В вашем примере у вас есть:
char *str1 = "Abcde";
Строковый литерал "Abcde"
соответствует объекту анонимного массива типа char[6]
(5 для длины строкиплюс 1 для завершающего '\0'
нулевого символа). Таким образом, sizeof "Abcde" == 6
.
Но str1
не является указателем на этот объект массива;это просто указатель на его начальный элемент, который содержит символ 'A'
. Если мы хотим получить доступ к другим элементам массива (символам 'b'
, 'c'
и т. Д.), Нам нужно выполнить арифметику указателей , чтобы продвигать указатель через элементы объекта массива.
Итак, изначально *str1 == 'A'
- но после ++str1
, `* str1 == 'b'.
Если вы хотите напечатать значение строки, вы можете сделать:
printf("%s\n", str1);
и функция printf
внутренне выполнят арифметику указателя, необходимую для продвижения по символам строки.
И именно поэтому sizeof (*str) == 1
. Он указывает только на один элемент объекта массива. Мы можем использовать его для доступа к другим элементам, но само значение указателя не несет никакой информации о том, насколько велик массив. (Для этого и используется терминатор '\0'
, поэтому мы можем распознать конец строки, не зная заранее, насколько он большой.)
Обратите внимание, что у вас может указатель нацелый объект массива:
char (*array_ptr)[6] = &"Abcde";
и sizeof *array_ptr == 6
- но это не так полезно, как вы могли ожидать. array_ptr
может указывать только на массив из ровно 6 элементов, а поскольку такие функции, как printf
и strlen
требуют указателей char*
, вы не можете напрямую манипулировать массивом с помощью array_ptr
. (Указатели на объекты массива действительно появляются, когда вы имеете дело с многомерными массивами - массивами массивов.)
Указатели на элементы массива, в отличие от целых объектов массива, гораздо более гибкие, и стандартная библиотекаиспользует их широко. Недостатком является то, что вы должны сами следить за размером массива, например, передавая его в качестве дополнительного аргумента или используя значение Sentinel, например, '\0'
, чтобы отметить конец массива.