Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is function(char * array[]) a valid function definition but not (char (*array)[] in C?

Tags:

c

I think that it is because the former is an array of pointers to char and the latter is a pointer to an array of chars, and we need to properly specify the size of the object being pointed to for our function definition. In the former;

function(char * p_array[])

the size of the object being pointed to is already included (its a pointer to char), but the latter

function(char (*p_array)[])

needs the size of the array p_array points to as part of p_array's definition? I'm at the stage where I've been thinking about this for too long and have just confused myself, someone please let me know if my reasoning is correct.

like image 720
Matt Avatar asked Aug 04 '11 04:08

Matt


People also ask

What does char * [] mean in C?

char* is a pointer to a character, which can be the beginning of a C-string. char* and char[] are used for C-string and a string object is used for C++ springs. char[] is an array of characters that can be used to store a C-string.

What's difference between char's [] and char * s in C?

Difference between char s[] and char *s in CThe s[] is an array, but *s is a pointer. For an example, if two declarations are like char s[20], and char *s respectively, then by using sizeof() we will get 20, and 4.

What is the difference between char * and char []?

The fundamental difference is that in one char* you are assigning it to a pointer, which is a variable. In char[] you are assigning it to an array which is not a variable.

Can a function return a char array in C?

C programming does not allow to return an entire array as an argument to a function. However, you can return a pointer to an array by specifying the array's name without an index.


1 Answers

Both are valid in C but not C++. You would ordinarily be correct:

char *x[]; // array of pointers to char
char (*y)[]; // pointer to array of char

However, the arrays decay to pointers if they appear as function parameters. So they become:

char **x; // Changes to pointer to array of pointer to char
char (*y)[]; // No decay, since it's NOT an array, it's a pointer to an array

In an array type in C, one of the sizes is permitted to be unspecified. This must be the leftmost one (whoops, I said rightmost at first). So,

int valid_array[][5]; // Ok
int invalid_array[5][]; // Wrong

(You can chain them... but we seldom have reason to do so...)

int (*convoluted_array[][5])[][10];

There is a catch, and the catch is that an array type with [] in it is an incomplete type. You can pass around a pointer to an incomplete type but certain operations will not work, as they need a complete type. For example, this will not work:

void func(int (*x)[])
{
    x[2][5] = 900; // Error
}

This is an error because in order to find the address of x[2], the compiler needs to know how big x[0] and x[1] are. But x[0] and x[1] have type int [] -- an incomplete type with no information about how big it is. This becomes clearer if you imagine what the "un-decayed" version of the type would be, which is int x[][] -- obviously invalid C. If you want to pass a two-dimensional array around in C, you have a few options:

  • Pass a one-dimensional array with a size parameter.

    void func(int n, int x[])
    {
        x[2*n + 5] = 900;
    }
    
  • Use an array of pointers to rows. This is somewhat clunky if you have genuine 2D data.

    void func(int *x[])
    {
        x[2][5] = 900;
    }
    
  • Use a fixed size.

    void func(int x[][5])
    {
        x[2][5] = 900;
    }
    
  • Use a variable length array (C99 only, so it probably doesn't work with Microsoft compilers).

    // There's some funny syntax if you want 'x' before 'width'
    void func(int n, int x[][n])
    {
        x[2][5] = 900;
    }
    

This is a frequent problem area even for C veterans. Many languages lack intrinsic "out-of-the-box" support for real, variable size, multidimensional arrays (C++, Java, Python) although a few languages do have it (Common Lisp, Haskell, Fortran). You'll see a lot of code that uses arrays of arrays or that calculates array offsets manually.

like image 167
Dietrich Epp Avatar answered Nov 15 '22 01:11

Dietrich Epp