В большинстве случаев выражение типа «N-элемента массива T
» будут преобразованы («распад») к выражению типа «указатель на T
», а значение выражения будет адрес первого элемента массива.
Исключения из этого правила являются:
- когда выражение массива операнд из
sizeof
или одинарных &
операторов;
- , когда выражение массива является строка символов используются для инициализации другого массива в объявлении (таким образом,
"welcome back "
строки символов, используемом для инициализации c
является не преобразуется в выражение указателя, вместо этого, содержимых строк буквальных копируются до c
).
Когда вы звоните
len=strlen1(c);
выраженияc
преобразуются из типа «14-элементный массив char
» в «указатель на char
», и это выражение указателя является то, что на самом деле получает передаются strlen1
.
В контексте объявления параметра функции T a[N]
и T a[]
обрабатываются так же, как T *a
; a
объявлен как указатель на T
, а не на массив T
. Это имеет смысл, поскольку функция не может получать выражение массива в качестве параметра; он будет преобразован в указатель перед передачей функции.
, то почему он печатает весь массив
Вот как работает спецификатор %s
преобразования; он сообщает printf
, чтобы начать печатать последовательность символов, начиная с адреса, указанного s
, пока не увидит 0-значный байт.
его размер составляет всего 8
Типом выраженияs
является char *
, так sizeof s
эквивалентно sizeof (char *)
(то есть, размер указателя char
), так, что вам 're display - количество байтов, необходимых для хранения указателя , а не размера строки, на которую указывает s
.
Вот карта памяти о том, как вещи играть на моей платформе, которая может помочь понять некоторые из этих понятий:
Item Address 00 01 02 03
---- ------- -- -- -- --
"welcome back " 0x400c89 77 65 6c 63 welc
0x400c8d 6f 6d 65 20 ome.
0x400c91 62 61 63 6b back
0x400c95 20 00 25 64 ..%d
c 0x7fffa9c401a0 77 65 6c 63 welc
0x7fffa9c401a4 6f 6d 65 20 ome.
0x7fffa9c401a8 62 61 63 6b back
0x7fffa9c401ac 20 00 00 00 ....
len 0x7fffa9c401bc 00 00 00 00 ....
s 0x7fffa9c400e8 a0 01 c4 a9 ....
0x7fffa9c400ec ff 7f 00 00 ....
p 0x7fffa9c40128 a0 01 c4 a9 ....
0x7fffa9c4012c ff 7f 00 00 ....
Это положение вещей на входе в strlen1
.
Сохраняется строковый литерал "welcome back "
, начинающийся по адресу 0x400c89
. Массив символов c
сохраняется с адреса 0x7fffa9c401a0
.Объект-указатель s
хранится начиная с адреса 0x7fffa9c400e8
и содержит адрес объекта объекта массива c
(x86 является малоподобным, поэтому он читает от младшего байта до наиболее значимого байта). Объект s
составляет всего 8 байтов, поэтому вы получили 8
в качестве вывода для sizeof(s)
.
Нельзя использовать спецификатор формата %d
для печати значения типа size_t
(это то, что возвращает sizeof
). Если вы используете C99 или более позднюю версию, используйте %zu
; если вы используете C89, используйте %lu
и привести значение к unsigned long
:
printf("size of s=%zu\n", sizeof s); // C99 or later
printf("size of s=%lu\n", (unsigned long) sizeof s); /* C89 */
В С «строка» представляет собой массив 'char's, по меньшей мере, один элемент равен '0'. – alk
Он печатает размер 8, потому что это размер указателя 'char *' в вашей системе. Кроме того, спецификатор формата '% d' ожидает аргумент типа' int', но ваш аргумент 'sizeof (s)' имеет тип 'size_t'. Вы можете исправить это, переведя аргумент в ожидаемый тип: '(int) sizeof (s)'. –
Возможный дубликат [Размер массива на языке программирования C] (http://stackoverflow.com/questions/1975128/sizeof-an-array-in-the-c-programming-language) –