cpointersmultidimensional-arraytypedef

Typedef for 2 dimensional array in C and access via a pointer


I create custom type for table (2 dimensional array):

typedef int table_t[4][2]; // 4 rows, 2 columns

Next, I declare table and pointer to the table:

table_t a = { { 10, 0 },    // my table
              { 20, 0 }, 
              { 30, 0 }, 
              { 40, 0 } };

table_t *b = &a;          // pointer to my table

Next, I try to print first column of the table:

    printf("%d\n", a[0][0]);    // var1. 
    printf("%d\n", a[1][0]);    // It's work    
    printf("%d\n", a[2][0]);
    printf("%d\n", a[3][0]);

It works. How can I get access to elements to the table over pointer to table_t?

I try to print first column of table over pointer:

    printf("%d\n", *b[0][0]);   // var2. 
    printf("%d\n", *b[1][0]);   // It's print true value only from *b[0][0] and
    printf("%d\n", *b[2][0]);   // some strange from other elements
    printf("%d\n", *b[3][0]);

Maybe I do something wrong? Suddenly for me next code works, but why the table has rotated? :

    printf("%d\n", *b[0][0]);   // var3
    printf("%d\n", *b[0][1]);   // Suddenly, it's work too.
    printf("%d\n", *b[0][2]);   
    printf("%d\n", *b[0][3]);

Godbolt demo: https://godbolt.org/z/7bb63vGxT


Solution

  • b has type pointer to a table_t, hence you should access the table via *b, and since postfix operators have a higher priority than prefix operators, you must parenthesize *b before dereferencing the table elements:

    void print_column_zero(table_t *b) {
        printf("%d\n", (*b)[0][0]);
        printf("%d\n", (*b)[1][0]);
        printf("%d\n", (*b)[2][0]);
        printf("%d\n", (*b)[3][0]);
    }
    
    [...]
    
        // passing a pointer to the table
        print_column_zero(&a);
    

    Note that instead of using a pointer to table_t, you could write:

    void print_column_zero(table_t b) {
        printf("%d\n", b[0][0]);
        printf("%d\n", b[1][0]);
        printf("%d\n", b[2][0]);
        printf("%d\n", b[3][0]);
    }
    
    [...]
    
        // passing a table, which decays to a pointer to its first element
        print_column_zero(a);
    

    Since table_t is a typedef for an array, this would be equivalent to: void print_column_zero(int (*b)[2])... and print_column_zero(&a[0]), ie: a pointer to the table elements would be passed, just as for void print_column_zero(table_t *b) but with a type that does not require dereferencing. The generated code should be very similar if not identical.

    Pointer to arrays are somewhat confusing and seldom used in practice. You might want to encapsulate your table in a structure instead:

    typedef struct table_t {
        int table[4][2]; // 4 rows, 2 columns
    } table_t;
    
    table_t a = {{ { 10, 0 },    // my table
                   { 20, 0 }, 
                   { 30, 0 }, 
                   { 40, 0 } }};
    
    void print_column_zero(table_t *b) {
        printf("%d\n", b->table[0][0]);
        printf("%d\n", b->table[1][0]);
        printf("%d\n", b->table[2][0]);
        printf("%d\n", b->table[3][0]);
    }
    
    [...]
    
        printf("%d\n", a.table[0][0]);
        printf("%d\n", a.table[1][0]);
        printf("%d\n", a.table[2][0]);
        printf("%d\n", a.table[3][0]);
    
        print_column_zero(&a);    // same output
    
        table_t *b = &a;          // pointer to my table
        print_column_zero(b);     // same output again
    

    This approach does not add any overhead compared to the previous ones, yet the struct encapsulation allows for related data to be added as may become useful and enables copying the table with a single assignment operation.