C array/pointer 语义:如何使结构内的数组具有相应指针的 properties/semantics?

C array/pointer semantics: how to make an array inside a struct to have properties/semantics of corresponding pointer?

考虑这段代码:

void f_01( int a, char** flags )
{
    printf("flags %p\n", flags);
    if ( ! flags ) 
    {
        return; // early exit
    }
    //some code
}

struct s01
{
    int     a;
    char**  flags1;     /* NULL = not used  */
    char*   flags[];    /* NULL = not used  */
} s_01 = { 13 };

int main()
{
    struct s01* s = &s_01;
    f_01( 1, NULL );
    f_01( 2, s->flags1 );//for demonstration purpose
    f_01( 3, s->flags ); //s->flags is expected to be NULL, but instead
                         //it evaluates to address of s->flags (i.e. &s->flags)
    return 0;
}

实际输出:

f_01 1 (nil)
f_01 2 (nil)
f_01 3 0x601038

预期输出(虚数):

f_01 1 (nil)
f_01 2 (nil)
f_01 3 (nil)

问题:如何让一个数组结构体成员(本例中的flags)拥有对应指针(本例中的char**)的properties/semantics,即初始化为默认 NULL

这样做的目的:能够在 API 的实现中使用相同的逻辑(在本例中为 f_01),char** 参数用于 [=17] =] 指针和 empty arrays。 IE。在 API 中没有额外的 if (! *flags) 检查,因为预计如果 flags != NULL 那么它就是 non-empty array。这是合乎逻辑的,对吧?那么为什么需要添加额外的 if (! *flags) 检查来处理 empty arraysempty array 能否以某种方式评估为 C 中的 NULL 指针?

结构未将 flags 初始化为 NULL 的原因是因为最后一个标志是 "flexible array member" 而不是指针。该结构是一种为您想要放入其中的所有内容分配足够 space 的方法。因此,当结构具有 int a;char** flags1;char* flags[]; 时。它需要分配至少 sizeof(a)(可能是 16 位)、sizeof(char**)(可能是 32 位)和 sizeof(char*[])(在这种特殊情况下未知)的内存块。因为我们还不知道指针数组的大小,所以它会将其视为零位,当您计算出所需的大小时,您需要为数组的大小分配足够的额外位。 (参见 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf §6.7.2.1 18-21)

所以在这种情况下它将 char* 指针初始化为 NULL 因为它没有被赋予一个值并且假设你想要一个大小为零的 char* 数组因为它没有为其大小赋予价值。该数组只是从结构的末尾开始(在您的情况下为 0x601038)。因此,当您将数组传递给 f_01 时,您就是在给它零数组的起始位置。

我知道您可能不想听到这个,但我能想到的唯一解决方案是将 char* flags[]; 替换为 char** flags。也许您可以将 char* flags[]; 更改为 int sizeOfFlags;char* flagData[];,然后将 sizeOfFlags 填入 f_01。因为 NULL == 0 如果 sizeOfFlags == 0 当大小为零时它仍然会给你 NULL。然而,这绝对是错误的做法。