C数组/指针的语义:如何使结构内部的数组具有相应指针的属性/语义?

问题描述 投票:1回答:1

考虑此代码:

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**),即默认情况下初始化为NULL

此目的:能够在API的实现中使用相同的逻辑(在此示例中为f_01),并为char**指针和NULL使用empty arrays参数。即在API中,没有其他if (! *flags)检查,因为预计如果flags != NULL则为non-empty array。这是合乎逻辑的,对吗?那么,为什么需要添加其他if (! *flags)检查来处理empty arrays?是否可以通过某种方式将empty array评估为C中的NULL指针?

c arrays pointers c99 semantics
1个回答
0
投票

结构之所以没有将flags初始化为NULL的原因是,最后一个标志是“ flexible array member”而不是指针。 struct是一种为要放入其中的所有事物分配足够空间的方法。因此,当结构具有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.118-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。但这绝对是错误的方法。

© www.soinside.com 2019 - 2024. All rights reserved.