Причина, по которой вы можете печатать strings
в main()
, но не в print_array
, является результатом преобразования массива в указатель при доступе.Это означает, что при доступе к массиву (с учетом 4 исключений ниже) массив преобразуется в указатель на первый элемент в массиве.После преобразования, как это происходит при передаче массива в качестве параметра функции, у вас есть только указатель, а не массив.
Стандарт C11 (как и стандарт C17) читается какследует:
Преобразование указателя массива
(p3) За исключением случаев, когда это операнд оператора sizeof
, оператора _Alignof
или унарный '&'
оператор, или строковый литерал , используемый для инициализации массива, выражение с типом "массив типа" преобразуется в выражение с типом "указатель на типMsgstr " указывает на начальный элемент объекта массива и не является lvalue. C11 Standard - 6.3.2.1 Другие операнды - L-значения, массивы и обозначения функций (p3)
Если вы заметите выше, при использовании с оператором sizeof
массив не преобразуетсяна указатель, поэтому в main()
, sizeof(strings) / sizeof(strings[0])
предоставляет количество элементов в массиве строки.Однако после передачи strings
в print_array
преобразование в указатель уже произошло, так что в print_array
ваша попытка использования sizeof
приводит к:
size_t array_length = sizeof(a_pointer) / sizeof(a_char);
(что является 8
на x86_64 или 4
на x86)
У вас есть два варианта (1) передать количество элементов в вашем массиве в качестве второго параметра в print_array
, или (2) делает последние указатели в strings
NULL
(для использования в качестве часового значения).Затем в print_array
вы можете просто перебрать strings[i]
, пока оно не станет NULL
.
Несколько быстрых примеров:
Передача количества элементов
#include <stdio.h>
void print_array (char **strings, size_t nptrs)
{
for (size_t i = 0; i < nptrs; i++)
printf("%s, ", strings[i]);
putchar ('\n');
}
int main(void) {
char *strings[] = { "Hello",
"Zerotom",
"new" };
print_array (strings, sizeof strings/sizeof *strings);
return 0;
}
Пример использования / вывода
$ ./bin/prnarray
Hello, Zerotom, new,
Добавление Sentinel NULL
в strings
#include <stdio.h>
void print_array (char **strings)
{
for (size_t i = 0; strings[i]; i++)
printf("%s, ", strings[i]);
putchar ('\n');
}
int main(void) {
char *strings[] = { "Hello",
"Zerotom",
"new",
NULL }; /* sentinel NULL */
print_array (strings);
return 0;
}
(тот же вывод)
Существует, по крайней мере, несколько способов зацикливания, используя либо циклы for
или while
и либо используя указатель на strings
и арифметику указателей, либо используя индексирование массива (Разница заключается в простой семантике, поскольку вы делаете то же самое).Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.