2

New to C, having trouble passing pointers. I am trying to pass this 2D array of pointers which points to strings (char[]s). I keep getting the error that I can't use %s because in the function call I declare the parameter as a char. However if I use %c I only print the first three characters of 'H' 'e' 'l' and then I get a segmentation fault.

Error Code:
    format specifies type 'char *' but the argument has type 'char' [-Wformat]
                            printf("%s ", in[i][j]);
                                    ~~    ^~~~~~~~
                                    %c

Suggestions?

void printArray(char *in[]){
int i;
int j;
for (i = 0; i < 3; i++){
    for (j = 0; j < 3; j++){
        printf("%c ", in[i][j]);
    }
}


 main(){
        char *arr1[3][3];
        arr1[0][0] ="Hello";
        arr1[0][1] = "World";
        arr1[0][2] = "Today";
        arr1[1][0] = "Is";
        arr1[1][1] = "September";
        arr1[1][2] = "28";
        arr1[2][0] = "th";
        arr1[2][1] = "2021";
        arr1[2][2] = "yay";
        char *j = arr1[0][0];
        int k; 
        int p;
        printf("Before: \n");
        printArray(&j);

To reiterate, the goal is send the array of strings and then print them in the function "printArray"

Sorry if this is an easy question, again very new to C

Thank you

  • 1
    Forget `j` ... `printArray(arr1[0]);` ==> https://ideone.com/Nvs3xL – pmg Sep 28 '21 at 15:10
  • @pmg: The code behind the link you posted is not what OP intended. OP wants to print all 9 words in the multidimensional array. Instead, your code prints the first 3 characters of the first 3 words of the array. – Andreas Wenzel Sep 28 '21 at 15:30
  • Does this answer your question? [C: 'the incompatible pointer types passing' warning is important?](https://stackoverflow.com/questions/68063801/c-the-incompatible-pointer-types-passing-warning-is-important) – Ahmet Dundar Sep 28 '21 at 15:56

3 Answers3

4

change
printArray(char *in[])
to
printArray(const char * in[][3])

and
printArray(&j)
to
printArray(arr1)

Then, you should be able to use %s.

You're passing a 1D array and wanting to use it as 2D in printing.

kalyanswaroop
  • 403
  • 4
  • 5
  • 1
    that gives the error: array has incomplete element type 'char *[]' void printArray(char *in[][]) –  Sep 28 '21 at 15:20
  • 1
    Try specifyng the sizes. – Neil Sep 28 '21 at 15:24
  • It is only necessary to specify one of the dimension sizes in the function prototype, but you might as well specify both. – Andreas Wenzel Sep 28 '21 at 15:27
  • Maybe [this is what you want](https://cdecl.org/?q=declare+pointer+to+array+3+of+array+3+of+pointer+to+char)? – Neil Sep 28 '21 at 15:30
  • 2
    Fixed error. An array can only have the first dimension unspecified. When trying the code, I had all the strings as const char *. That doesnt have to be. I just did. The main thing is that in C/C++, you have to specify all array dimensions except the first one. – kalyanswaroop Sep 28 '21 at 15:35
4

Use variable length arrays (VLAs). They were added to C exactly for this purpose:

void printArray(int n, int m, char *in[n][m]){
  for (int i = 0; i < n; i++){
    for (int j = 0; j < m; j++){
        printf("%s ", in[i][j]);
    }
  }
}


int main() {
  char *arr1[3][3];
  ... initialize arr1
  printArray(3, 3, arr1);
}

EDIT

As stated in the comment the size expression in [n] could be omitted as it is ignored by the compiler. Though it is still useful for self-documenting. The alternative declaration could be:

void printArray(int n, int m, char *in[static n][m])

The keyword static instructs the compiler that at least first n elements of pointed by in are valid.

tstanisl
  • 13,520
  • 2
  • 25
  • 40
  • I think that `[n][m]` are totally ignored on the function prototype, but they are arguably self-documentation. – Neil Sep 28 '21 at 15:38
  • 2
    @Neil: The `n` is probably ignored, but it cannot ignore the `m`. Without knowing the value of `m`, the compiler cannot calculate the memory address of `in[i][j]`. – Andreas Wenzel Sep 28 '21 at 15:41
  • 1
    I don't think that OP requires a VLA. A fixed-length array would probably have been good enough. However, I am still upvoting this answer, because it makes the function more flexible. Note that not all C11-compliant compilers support VLAs, as it is an optional feature of the language. It is only a mandatory feature in C99, but C11 demoted the feature to optional. – Andreas Wenzel Sep 28 '21 at 15:42
0

If you want a fixed-size array, you have to trust the programmer to pass it's size, like in @tstanisl answer. That's because in C, arrays passed to functions decay to pointers. In @kalyanswaroop answer, the size is trusted to be 3, but that's never checked by the type-checker, (that may or may not be important to you.) Yet another way to pass an array to a function is with a pointer, that way the static type-checker can make sure the sizes match. (Using cdecl.)

void printArray(char *(*in)[3][3]) {
    size_t i, j;
    for(i = 0; i < sizeof *in / sizeof **in; i++) {
        for(j = 0; j < sizeof **in / sizeof ***in; j++) {
            printf("%s ", (*in)[i][j]);
        }
    }
}

This changes the prototype; you would call it as printArray(&arr1).

Neil
  • 1,767
  • 2
  • 16
  • 22