Home > Blockchain >  Why I got a warning when I pass 2D array in function with constant parameter whilst in 1D everything
Why I got a warning when I pass 2D array in function with constant parameter whilst in 1D everything

Time:04-01

I have the following two similar codes Snippet 1:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define W 5
#define N 9


void print_w(const char x[W] [N 1]);


int main()
{
     char words[W][N   1]={{}};
     print_w(words);
     printf("R*E*V*E*R*E*S*E\n");
     print_w( (const char (*) [N 1]) words);
     return 0;
}



void print_w(const char x[W] [N 1]){
    int i;

    for (i=0; i<W; i  ) {
        printf("Word (%d) :%s\n", i, x[i]);
    }
    return;
}

Snippet 2:

#include <stdio.h>
#include <stdlib.h>
#define N 9

void printString(const char []);

int main(){
    char mystr[N   1];
    scanf("%9s", mystr);
    printString(mystr);
    printString( (const char (*) ) mystr);
    return 0;
}

void printString(const char str[]){
    int i;
    for (i=0; str[i]!=0; i  ) {
         printf("%c\n", str[i]);
    }
}

In snippet 1 I have a warning telling me that in line print_w(words);:

[Warning] passing argument 1 of 'print_w' from incompatible pointer type

Implying that I have to make a typecast in print_w( (const char (*) [N 1]) words);

While in snippet 2 this is not the case with my code as I have performed both options without warnings.

Why there is a warning in the first example and not in the second? I suppose that passing wrong variable type (char --> const) in the function is not the case because a warning will occured also in snippet 2.

CodePudding user response:

This is a defect in the C standard; a pointer to an array of char is not compatible with a pointer to an array of const char and may not be passed (with defined behavior) as an argument for a parameter of type pointer to an array of const char.

Note that after the automatic conversion of arrays, print_w(words) passes a pointer to an array to print_w, not an array of arrays, and, after the automatic adjustment of array parameters, void print_w(const char x[W] [N 1]) declares printString to have a parameter of type pointer to array, not array of array. So we are concerned with the rules for pointers to arrays.

For char (*)[N 1] and const char (*)[N 1], we first consider whether these pointer types are compatible. Per C 2018 6.7.6.1 2, for two pointer types to be compatible, they must point to compatible types.

They point to arrays, so we look 6.7.6.2 6, which says, for two array types to be compatible, both shall have compatible element types.

For the elements, we look to 6.7.3 11, which says, for two qualified types to be compatible, both shall have the identically qualified version of a compatible type. char and const char are not identically qualified, so they are not compatible, so the array types are not compatible, so the pointer types are not compatible.

Function calls allow passing arguments for parameters if an assignment to the parameter type is allowed, per C 6.5.2.2 2. Per 6.5.16.1 1, assignment allows “adding” a qualifier to the pointed-to type. For example, a pointer to char can be assigned to a pointer to const char. This is why the void printString(const char []) code does not yield an error or warning message. However, the rules do not allow adding a qualifier deeper in the type. So a pointer to an array of char cannot be assigned to a pointer to an array of const char.

This is a defect in the C standard. There is some work in the C committee to fix this. In draft N2731, 6.2.5 28 says “… An array and its element type are always considered to be identically qualified.…” This could make the interpretation of the assignment that a pointer to an array of char is being assigned to a pointer to a const-qualified array of char, which would be allowed.

In the meantime, when you use the -pedantic switch, GCC is pedantic. One remedy is not to ask it to be pedantic. Another is to use an explicit cast. Another is to use Clang or another compiler.

  • Related