Converting array of pointers to double pointer

后端 未结 3 1507
别跟我提以往
别跟我提以往 2021-01-27 09:51

I am able to do this:

char * months[] = {\"empty\",\"jan\",\"feb\",\"mar\",\"apr\",\"may\",\"jun\",\"jul\",\"aug\",\"sep\",\"oct\",\"nov\",\"dec\"};

unsigned sh         


        
3条回答
  •  清歌不尽
    2021-01-27 10:39

    Type Controls Everything

    char *months[] = {"empty","jan",...};
    

    Declares months as an array-of-pointers to char where the initializer completes the type providing the number of pointers in the array (the "How many?" information) and initializing each pointer to point to the beginning of a valid character string. The complete type is char *[13] (an array of 13 pointers.

    If you simply tried to declare:

    char *months[];
    

    You compiler would throw an error complaining that months was in incomplete type.

    After months has been declared and initialized, then by operation of C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3), on access, months is type-compatible with char** as the first level of indirection is converted to a pointer to the first element, resulting in months being char** on access (subject to the 4 exceptions in the rule).

    Why Can't I Just Declare char **months = {"empty","jan",...}; To Begin With?

    With a pointer-to-pointer-to-type there is no array involved at all. How many pointers are declared? While with char *months[]... the initializer for the array can complete the type and provide for the number of elements in an array, with char **months, you simply have a (pointer)-to-pointer with NO array involved at all. Meaning following the declarations of:

    char **months;
    

    months is simply an uninitialized pointer holding some indeterminate address. Any attempt to change the content of the indeterminate memory location results in Undefined Behavior (and likely a SegFault). The C-standard simply does not provide for initialization of a pointer-to-pointer as it does for an Array. C11 Standard - 6.7.9 Initialization

    It fails to build with a excess elements in scalar initializer. What does that mean exactly, and how would I initialize the above using a pointer to pointers?

    The error, while a bit subtle, makes perfect sense. You have a single pointer when you declare:

    char **months;
    

    If you try to initialize the single pointer with an initializer-list, e.g.

    char **months = { "empty", "jan", "feb", ... };
    

    There a are whole lot more than 1 excess element in the initializer...

    You have two ways to initialize a pointer-to-pointer-to-type. (1) You can either allocate the number of pointers you need, e.g.

    char **months = malloc (13 * sizeof *months);  /* allocate 13 pointers */
    

    and then allocate for, or assign, a valid address to the first character in a character string to each of the 13-pointers, e.g. months[0] = "empty"; months[1] = "jan", ...; or

    (2) you can assign the valid address of a (single) object that is type-compatible with your pointer, e.g.

    char **my_months = months;
    

    You can then access each individual string with my_months[0], because the pointer-to-pointer now points to valid storage and the type is complete such that my_months + 1 points to the next string after the current. For example:

    #include 
    
    int main (void) {
    
        char *months[] = { "empty", "jan", "feb", "mar", "apr", "may", "jun", 
                            "jul", "aug", "sep", "oct", "nov", "dec" };
        char **my_months = months;
        size_t n = sizeof months / sizeof *months;
    
        for (size_t i = 0; i < n; i++)
            printf ("my_months[%2zu] : %s\n", i, my_months[i]);
    }
    

    Example Use/Output

    $ ./bin/my_months
    my_months[ 0] : empty
    my_months[ 1] : jan
    my_months[ 2] : feb
    my_months[ 3] : mar
    my_months[ 4] : apr
    my_months[ 5] : may
    my_months[ 6] : jun
    my_months[ 7] : jul
    my_months[ 8] : aug
    my_months[ 9] : sep
    my_months[10] : oct
    my_months[11] : nov
    my_months[12] : dec
    

    Look things over and let me know if you have further questions.

提交回复
热议问题