1

I'm trying to understand pointers in C and I think I have an okay grasp so far. I am trying to make sense of arrays and how they are passed to functions. It is my understanding that when passing an array to a function it is passed by reference and that when passing an array to a function it points to the beginning of the array in memory or the first memory address of the array. So if I create an array like so:

char* arr[2] = {"Andrew", "Schools"};

I could define the following functions to accept this array which is really passing a pointer to the first item in the array:

void readSingleArray(char* arr[], int count) {
  for(int i=0; i<count; i++) {
    printf("%s\n", arr[i]);
  }
}

void readSingleArray2(char** arr, int count) {
  for(int i=0; i<count; i++) {
    printf("%s\n", arr[i]);
  }
}

The second function accepts char** arr instead of char* []. So I understand this as such: since I have an array of pointers, this is telling the compiler that I want to access a pointer to a char so either way will work.

Now if I define a multi-dimensional array like so:

char* arr2[2][2] = {{"Andrew", "Schools"},{"Computer", "Programmer"}};

I can define the following function:

void readMultiDimArray(char* arr[2][2], int count, int count2) {
  for(int i=0; i<count; i++) {
    for(int x=0; x<count2; x++) {
      printf("%s\n", arr[i][x]);
    }
  }
}

But not this function:

void readMultiDimArray2(char** arr, int count, int count2) {
    for(int i=0; i<count; i++) {
    for(int x=0; x<count2; x++) {
      printf("%s\n", arr[i][x]);
    }
  }
}

I read that multi-dimensional arrays are actually single dimensional arrays or one single block of memory and the compiler will figure out how to access the appropriate array items: How to pass a multidimensional array to a function in C and C++. This makes sense to me so my question is: Why can I use a char** arr for single arrays but when using multi-dimensional array this won't work. Because how I see it, no matter what, I only need to access the first memory address of the array since it's always going to be one continuous block of bits

Community
  • 1
  • 1
Andrew Schools
  • 321
  • 3
  • 10
  • 2
    I think your examples get a bit difficult because you are using arrays of `char*`, so arrays where the base element is a pointer. First, try to think things trough for situations where the base element is e.g `double`. – Jens Gustedt Jun 06 '15 at 17:10
  • `readMultiDimArray2` will not work properly. If you did what Jens Gustedt suggested you would see why. – JS1 Jun 06 '15 at 17:12
  • @JS1 - You are right. readMultiDimArray2 doesn't compile like I thought it did which throws the entire question off. – Andrew Schools Jun 06 '15 at 17:26
  • I updated question. I will also do what @Gustedt mentioned. – Andrew Schools Jun 06 '15 at 17:35

1 Answers1

1

These function declarations

void readMultiDimArray(char* arr[2][2], int count, int count2) {
  for(int i=0; i<count; i++) {
    for(int x=0; x<count2; x++) {
      printf("%s\n", arr[i][x]);
    }
  }
}

void readMultiDimArray2(char** arr, int count, int count2) {
    for(int i=0; i<count; i++) {
    for(int x=0; x<count2; x++) {
      printf("%s\n", arr[i][x]);
    }
  }
}

are not equivalent and the second function declaration is wrong if you are going to pass an array declared like char* arr2[2][2]; as an argument of the function. A correct function declaration will look at least like

void readMultiDimArray2( char * ( *arr )[2], int count, int count2) {
    for(int i=0; i<count; i++) {
    for(int x=0; x<count2; x++) {
      printf("%s\n", arr[i][x]);
    }
  }
}

If you have an array declared like

T array[N];

where T some type then when the array is passed to a function that has the same parameter declaration then it is converted to pointer to its first element. That is it will have type

T *ptr;

So if you have an array declared like this

char* arr2[2][2];

then you can redeclare it the following way

typedef char * T[2];

T arr2[2];

According to the explanation above it will be converted like

T *ptr;

when it will be passed as an argument.

Now substitute T for its actual type and you will get

char * ( *ptr )[2];

where char *[2] is the type of the element of array arr2

Each two-dimensional array is in fact a one-dimensional array elements of which is in turn one-dimensional arrays. That is it is an array of arrays.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I think I understand why readSingleArray and readMultiDimArray work since you are accessing the first element in the array which happens to be a pointer. But why does readSingleArray2 work? Isn't this a pointer to a pointer? What is the difference between char* arr[] and char**? Does the compiler resolve this as being equal? – Andrew Schools Jun 06 '15 at 17:51
  • @Andrew Schools Reread my post. Array char *arr[2] can be represented like T arr[2]; where T is char *. So when the array is passed to the function it is converted to pointer to its first element T *ptr; Now replace T with char * and you will get char **ptr where char * is the type of objects pointed to by ptr. Thus for example ptr[0] will get an object of type char *.., – Vlad from Moscow Jun 06 '15 at 17:54
  • Let me re-read your example a bunch of times so I get a full understanding of what you said. – Andrew Schools Jun 06 '15 at 18:00
  • @Andrew Schools If something is unclear then ask a question. You may also ask a question in English in my personal forum at www.cpp.forum24.ru in the first section of the forum. – Vlad from Moscow Jun 06 '15 at 18:04
  • So if I understand you correctly, when we point to an array we want to specify a pointer to the first element of the array. For a single array of character strings, this type would be char** or char* []. For a multi-dimensional array of character strings with an inner dimension of 2, this type would be char* (*ptr)[2]. Am I understanding this correctly? – Andrew Schools Jun 07 '15 at 01:51
  • 1
    @Andrew Schools To copy a whole array when it is passed to a function as a parameter is inefficient, Arrays can be very big. So when you declare a function parameter as an array and pass an array designator as an argument then it is adjusted by the compiler to a pointer to its first element, Elements of a two-dimensional array are in turn one-dimensional arrays (rows). So when you pass a two-dimensional array as an argument it is converted to a pointer to its first one-dimensional array element (row). – Vlad from Moscow Jun 07 '15 at 07:00