T-D
T-D

Reputation: 373

what is the difference between the following 2D array declarations?

i cant seem to get this clear in my head especially when trying to pass the array as a parameter to a function

char *array[x][y];

and

char array[x][y];

i know both are 2D arrays and that i can pass the second declaration as a function parameter as follows: prototype

void check(char**);

then use it as

void check(char array[][]) {}

Upvotes: 0

Views: 187

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 753665

Here is some code to illustrate the differences between a 2D array of pointers as an argument and a char *** argument.

#define _XOPEN_SOURCE 700  // Declare strdup() on Linux
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static void function_taking_2d_array(int x, int y, char *array[x][y])
{
    printf("2D array:\n");
    for (int i = 0; i < x; i++)
        for (int j = 0; j < y; j++)
            printf("[%d,%d] = <<%s>>\n", i, j, array[i][j]);
}

static void function_taking_triple_pointer(int x, int y, char ***array)
{
    printf("Triple pointer:\n");
    for (int i = 0; i < x; i++)
        for (int j = 0; j < y; j++)
            printf("[%d,%d] = <<%s>>\n", i, j, array[i][j]);
}

int main(void)
{
    int x = 3;
    int y = 4;
    char *array[x][y];

    for (int i = 0; i < x; i++)
    {
        for (int j = 0; j < y; j++)
        {
            char buffer[32];
            snprintf(buffer, sizeof(buffer), "fixed string [%d][%d]", i, j);
            array[i][j] = strdup(buffer);
        }
    }

    function_taking_2d_array(x, y, array);

    char **aux[x];
    for (int i = 0; i < x; i++)
        aux[i] = array[i];

    function_taking_triple_pointer(x, y, aux);

    for (int i = 0; i < x; i++)
    {
        for (int j = 0; j < y; j++)
            free(array[i][j]);
    }

    return 0;
}

Compile cleanly with:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition -Werror c3d.c -o c3d
$

Sample output:

2D array:
[0,0] = <<fixed string [0][0]>>
[0,1] = <<fixed string [0][1]>>
[0,2] = <<fixed string [0][2]>>
[0,3] = <<fixed string [0][3]>>
[1,0] = <<fixed string [1][0]>>
[1,1] = <<fixed string [1][1]>>
[1,2] = <<fixed string [1][2]>>
[1,3] = <<fixed string [1][3]>>
[2,0] = <<fixed string [2][0]>>
[2,1] = <<fixed string [2][1]>>
[2,2] = <<fixed string [2][2]>>
[2,3] = <<fixed string [2][3]>>
Triple pointer:
[0,0] = <<fixed string [0][0]>>
[0,1] = <<fixed string [0][1]>>
[0,2] = <<fixed string [0][2]>>
[0,3] = <<fixed string [0][3]>>
[1,0] = <<fixed string [1][0]>>
[1,1] = <<fixed string [1][1]>>
[1,2] = <<fixed string [1][2]>>
[1,3] = <<fixed string [1][3]>>
[2,0] = <<fixed string [2][0]>>
[2,1] = <<fixed string [2][1]>>
[2,2] = <<fixed string [2][2]>>
[2,3] = <<fixed string [2][3]>>

A particular point to note is that the differences between the two functions are in the function name and signature and in the identifying message — the source for the rest of the function bodies is the same. Nevertheless, if you look at the assembler code for the two functions (assuming they weren't inlined for you), you'd see that they generate different instructions — because the types of the arguments are not the same.

Upvotes: 2

Mureinik
Mureinik

Reputation: 311188

The first is a two dimensional array of char* - i.e., char pointers, which are often used as stings in C. The second is a two dimensional array of chars - i.e., single characters.

Upvotes: 1

Related Questions