简体   繁体   English

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

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

Consider this code:考虑这段代码:

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;
}

Actual output:实际 output:

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

Expected output (imaginary):预期 output(虚构):

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

Question: how to make an array struct member ( flags in the example) to have properties/semantics of corresponding pointer ( char** in this example), ie to be initialized to NULL by default?问题:如何使数组结构成员(示例中的flags )具有相应指针的属性/语义(本示例中的char** ),即默认初始化为NULL

The purpose of this: to be able to use the same logic in the API's implementation ( f_01 in this example) with char** argument for both NULL pointers and empty arrays .这样做的目的:能够在 API 的实现(本例中为f_01 )中使用相同的逻辑,其中NULL指针和empty arrayschar**参数。 Ie inside the API there is NO additional if (! *flags) check because it is expected that if flags != NULL then it is non-empty array .即在 API 内部没有额外的if (! *flags)检查,因为预计 if flags != NULL那么它non-empty array It is logical, right?这是合乎逻辑的,对吧? Then why need to add additional if (! *flags) check to handle empty arrays ?那么为什么需要添加额外的if (! *flags)检查来处理empty arrays Can an empty array be evaluated somehow to NULL pointer in C?可以以某种方式将empty array评估为 C 中的NULL指针吗?

The reason why the struct doesn't initialize the flags as NULL is because the last flags is "flexible array member" and not a pointer.结构没有将flags初始化为NULL的原因是因为最后一个标志是“灵活数组成员”而不是指针。 The struct is a way of allocating enough space for all of the things that you want to put in it. struct 是一种为您想要放入其中的所有内容分配足够空间的方法。 So, when the struct has int a;所以,当结构有int a; , char** flags1; , char** flags1; , char* flags[]; , char* flags[]; . . It needs to allocate a chunk of memory that is at least sizeof(a) (probably 16 bits), sizeof(char**) (probaly 32 bits), and sizeof(char*[]) (in this particular case it is unknown).它需要分配一块 memory,它至少是sizeof(a) (可能是 16 位)、 sizeof(char**) (可能是 32 位)和sizeof(char*[]) (在这种特殊情况下是未知的)。 Because we don't know the size of the array of pointers yet, it will treat it as if it is zero bits and you will need to allocate enough additional bits for the size of the array when you figure out the size you need.因为我们还不知道指针数组的大小,所以它会将其视为零位,当您确定所需的大小时,您需要为数组的大小分配足够的额外位。 (see http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf §6.7.2.1 18-21) (见http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf §6.7.2.1 18-21)

So in this case it initializes the char* pointer as NULL because it wasn't given a value and assumes you want an array of char* that is zero in size because it wasn't given a value for its size.所以在这种情况下,它将char*指针初始化为NULL因为它没有被赋予一个值,并假设你想要一个大小为零的char*数组,因为它没有被赋予它的大小值。 This array simply starts at the end of of the struct (in your case 0x601038 ).该数组仅从结构的末尾开始(在您的情况下0x601038 )。 So when you pass the array into f_01 you are giving it the starting location of the zero array.因此,当您将数组传递给f_01时,您将为其提供零数组的起始位置。

I know that you probably don't want to hear this but the only solution that I can think of is to replace that char* flags[];我知道你可能不想听到这个,但我能想到的唯一解决方案是替换那个char* flags[]; with char** flags .带有char** flags Maybe you could make char* flags[];也许你可以制作char* flags[]; change into int sizeOfFlags;更改为int sizeOfFlags; and char* flagData[];char* flagData[]; then just feed sizeOfFlags into f_01.然后只需将 sizeOfFlags 输入 f_01。 because NULL == 0 if sizeOfFlags == 0 it will still give you NULL when the size is zero.因为NULL == 0如果sizeOfFlags == 0它仍然会给你NULL当大小为零时。 However that is definitely the wrong way to do it.然而,这绝对是错误的做法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM