0

Why this code doesn't work? I have some old code and don't want to allocate a in the heap.

void test(char **str) {
   cout << str[0] << endl;
   cout << str[1] << endl;
}

int main(int argc, char* argv[]) {
    char a[2][5];
    strcpy(a[0],"abc");
    strcpy(a[1],"def");

    char *str1 = (char *)a;
    test(&str1);

    return 0;
}
Christophe
  • 68,716
  • 7
  • 72
  • 138
K P
  • 51
  • 7
  • And what is the code supposed to do? – joao Dec 02 '15 at 12:11
  • 8
    If you ever find the need to use a C-style cast in C++, then it's usually a sign of you doing something you should not be doing and that might lead to undefined behavior. If the compiler gives you an error or a warning, then using a C-style cast will just silence the compiler, the problem isn't really solved (you fix the symptom and not the disease). – Some programmer dude Dec 02 '15 at 12:14
  • 2
    Oh, and you might want to read e.g. [this old answer of mine](http://stackoverflow.com/questions/18440205/casting-void-to-2d-array-of-int-c/18440456#18440456), which tries to describe the difference between an array of arrays and a pointer to pointer. – Some programmer dude Dec 02 '15 at 12:17
  • 1
    Arrays are not pointers. Pointers are not arrays. There is no relation what-so-ever between 2D arrays and pointer-to-pointers. You may be confusing things with a common way to store strings: a one-dimensional array of pointers to char - because a pointer to the first element in such a one-dimensional array of pointers would be a `char**`. – Lundin Dec 02 '15 at 12:26

3 Answers3

5

This code does not work because a pointer to pointer to char is not the same as a 2 by 5 array of char, with or without a cast:

  • A pointer to pointer can be used as an array of pointers, i.e. its elements can be dereferenced with * operator
  • A 2 by 5 array consists of ten items organized as two rows of five items each. None of these items is a pointer that could be dereferenced.

Here is how you can construct an array compatible with char**:

char a[2][5];
strcpy(a[0],"abc");
strcpy(a[1],"def");

char *str1[] = { a[0], a[1] };
test(str1);

Now str1 is an array of char pointers, with two items. The first item is a pointer containing the address of a[0]; the second item is a pointer containing the address of a[1]. An array of pointers can be passed to a function expecting a pointer to pointer, hence your test() function works correctly.

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

Why ?

Because char a[2][5] is a 2 dimensional array stored as 10 contiguous chars. But parameter char **str expects an array of pointers to one dimensional arrays of chars.

enter image description here

Solution 1:

Keep the function as it is, but pass it an array of pointers to char:

...
char *str1[2];
str1[0]=a[0];
str1[1]=a[1];
test(str1); 

Solution 2:

CHange the function to accept 2D arrays with 5 elements in the secund dimension (to pass an n dimensional array the last n-1 dimensions must be predefined):

void test(char str[][5]) {
    ...
}
int main() {
    ...
    test(a);
}

The inconvenience is that it is less flexible.

Solution 3

If your problem is specifically related to array of strings and not the more general issue of 2D array, switch from char* to std::string and you'll make your life easier !

void test(string str[]) {
   ...
}
int main(int argc, char* argv[]) {
    string a[2] ={ "abc","def" };
    test(a);
}
Christophe
  • 68,716
  • 7
  • 72
  • 138
0

Since you're using C++, you could change your test function to something like this:

template <int cols> void test(char arr2d[][cols]){
    /* whatever */
}

You'd then call it in your program passing a as argument (e.g test(a)), without any cast or other kind of transformation.

Paulo1205
  • 918
  • 4
  • 9