Зачем кому-то определять такой указатель? - PullRequest
1 голос
/ 15 марта 2020
const char** list_entry[] = 
{
    (const char*[]){"ent1", "ent2", "ent3", "ent4"},
    (const char*[]){"ent1", "ent2", "ent3", "ent4"}
};

Я не совсем понимаю, так как не мог придумать ничего, чего не смог бы сделать sh только с одним "*" вместо 2.

Каковы основные проблемы / преимущества за такие вещи?

1 Ответ

2 голосов
/ 15 марта 2020

В этом объявлении

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 **.

...