-1

Can a static array that is declared in main be initialized/mutated in a function?

I tried the code below but it returns a seg fault.

void initialize(int **p, int a, int b) 
{
    int i, j;
    for(i=0; i<a; ++i) {
        for(j=0; j<b; ++j)
            p[i][j] = j;
    }
}

int m = 5;
int n = 5;
int arr[m][n];
int **A = &arr[0][0];


initialize(A, m, n);

EDIT:

I found a good explanation of this issue here:

http://c-faq.com/aryptr/pass2dary.html

Mars
  • 4,677
  • 8
  • 43
  • 65

4 Answers4

2

You are passing an two dimensional array not a pointer to pointer. You will have to change the function argument type.

void initialize( int a, int b , int p[][b] ) 
{
    ...

Since you have to define the size for the array p, the arguments a and b are declared first and then b is used to determine the size.

2501
  • 25,460
  • 4
  • 47
  • 87
  • What if I declare and initialize a double pointer to the static array? – Mars Oct 14 '14 at 18:09
  • 2
    @Zaphod stop thinking a pointer-to-pointer is synonymous to an array of arrays. They're NOT the same. When looking at a pointer, consider it as a "pointer to a sequence of X" where X is the type of the pointer. A pointer to pointer therefore is "a pointer to a sequence of **pointers**. `Type arr[n][m]` is no such sequence. This answer is one correct way to pass an array of arrays to a function. In your question `arr` is an array of arrays. That does *not* express as a pointer-to-pointer when passed to a function, and as I said, however you concluded they were synonymous it is simply wrong. – WhozCraig Oct 14 '14 at 18:14
  • 1
    @2501. If I want to, could I do `int p[a][b]` instead of `int p[][b]`? Why the latter? – Mars Oct 14 '14 at 18:15
  • @Zaphod You can do both as long as every, but the first, dimension is declared. – 2501 Oct 14 '14 at 18:15
  • @2501. Why must the first dimension not be declared? – Mars Oct 14 '14 at 18:17
  • 2
    @Zaphod: From compiler's point of view both `int p[a][b]` and `int p[][b]` are translated to `int (*p)[b]` anyway, that is first dimension is simply ignored, thus there no point putting it, moreover it may be misleading for someone who doesn't know C that well. – Grzegorz Szpetkowski Oct 14 '14 at 18:24
  • 1
    @Zaphod: In the context of a function parameter declaration, `T a[]` and `T a[N]` are both interpreted as `T *a`; they declare `a` as a *pointer* to `T`, not as an array of `T`. Thus, `T a[][N]` is equivalent to `T (*a)[N]`; `a` is a pointer to an `N`-element array of `T`. That's why you don't need to specify the innermost dimension; it isn't used in this context. However, if you do use it in the declaration of `a`, it must be declared *before* `a` - `foo( int a, int b, int p[a][b] )`. – John Bode Oct 14 '14 at 18:26
  • @Zaphod As for why do you need dimensions in the first place, a 2d array is contiguous in memory and you need to know how many places to skip when you iterate trough the outer dimension, and the size of the inner dimension gives you that information. Try it on paper. – 2501 Oct 14 '14 at 18:27
  • @2501 fyi, that "places to skip" verb-age has a shorter vernacular. It is called the *stride* of an array dimension. – WhozCraig Oct 14 '14 at 18:31
1

Enable the warnings in your compiler and you'll get this:

warning: passing argument 1 of ‘initialize’ from incompatible pointer type [enabled by default]

As a result, you receive a seg. fault.

You need to change the prototype of your function to this:

void initialize(int a, int b, int p[][b]);

and the calling of the function will be:

initialize(m, n, A);
gsamaras
  • 71,951
  • 46
  • 188
  • 305
1

Yes, they can, wouldn't be very useful if they couldn't.

However you've encountered a problem with the way you're trying to decay arrays into pointers there. What you've declared in main is a two-dimensional array - a single block of memory that happens to be indexed through a combination of the two indices (translated at compile-time). You're trying to decay it as though it was an array of pointers to arrays - meaning that within initialize, you're dereferencing the pointer, to try to get a pointer, and then dereferencing that to get a slot. Since a two-dimensional array actually describes a single block of memory, two layers of pointer indirection won't work to access it. You need to decay it to a type involving only one level of pointer indirection.

Alex Celeste
  • 12,824
  • 10
  • 46
  • 89
0

Change

initialize(A, m, n);
void initialize(int **p, int a, int b)

to

initialize(n, A, m);
void initialize( int b, int p[][b], int a) 

When you are passing a multidimensional array to a function, the first array dimension does not have to be specified. However the second(and subsequent) dimensions must be provided to the function.

ani627
  • 5,578
  • 8
  • 39
  • 45