В этом объявлении
const char** list_entry[] =
{
(const char*[]){"ent1", "ent2", "ent3", "ent4"},
(const char*[]){"ent1", "ent2", "ent3", "ent4"}
};
используются два составных элемента: литералы
(const char*[]){"ent1", "ent2", "ent3", "ent4"},
(const char*[]){"ent1", "ent2", "ent3", "ent4"}
, которые имеют автоматическое c или статическое c время хранения в зависимости от того, где происходит объявление.
Без составных литералов вам потребуется определить два отдельных именованных массива указателей на строковые литералы, а затем объявить list_entry
, используя эти именованные массивы.
Вот демонстрационная программа, которая показаны два альтернативных подхода к определению массива list_entry
с использованием составных литералов и без использования составных литералов.
#include <stdio.h>
int main(void)
{
{
const char** list_entry[] =
{
(const char*[]){ "ent1", "ent2", "ent3", "ent4", "" },
(const char*[]){ "ent1", "ent2", "ent3", "ent4", "" }
};
size_t N = sizeof( list_entry ) / sizeof( *list_entry );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; list_entry[i][j][0] != '\0'; j++ )
{
printf( "%s ", list_entry[i][j] );
}
putchar( '\n' );
}
}
putchar( '\n' );
{
const char *list1[] = { "ent1", "ent2", "ent3", "ent4", "" };
const char *list2[] = { "ent1", "ent2", "ent3", "ent4", "" };
const char** list_entry[] = { list1, list2 };
size_t N = sizeof( list_entry ) / sizeof( *list_entry );
for ( size_t i = 0; i < N; i++ )
{
for ( size_t j = 0; list_entry[i][j][0] != '\0'; j++ )
{
printf( "%s ", list_entry[i][j] );
}
putchar( '\n' );
}
}
return 0;
}
Его вывод
ent1 ent2 ent3 ent4
ent1 ent2 ent3 ent4
ent1 ent2 ent3 ent4
ent1 ent2 ent3 ent4
Из второго фрагмента кода ясно например, массив list1
const char *list1[] = { "ent1", "ent2", "ent3", "ent4", "" };
является массивом указателей на первый символ строковых литералов. (Примечание: указатели массива, используемые в выражениях с редкими исключениями, преобразуются в указатели на их первые элементы. И строковые литералы являются символьными массивами.)
Этот массив указателей используется в качестве инициализатора в объявлении list_entry
const char** list_entry[] = { list1, list2 };
также преобразуется в указатель на свой первый элемент. Так как элемент list1 имеет тип const char *
, указатель на его первый элемент будет иметь тип const char **
.