为什么当我在带有常量参数的函数中传递二维数组时收到警告,而在一维中一切正常?

Why I got a warning when I pass 2D array in function with constant parameter whilst in 1D everything is normal?

我有以下两个相似的代码 片段 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;
}

片段 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]);
    }
}

在片段 1 中,我收到一条警告,告诉我在行 print_w(words);:

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

暗示我必须在 print_w( (const char (*) [N+1]) words);

中进行类型转换

虽然在代码片段 2 中,我的代码并非如此,因为我在没有警告的情况下执行了这两个选项。

为什么第一个示例中有警告,而第二个示例中没有?我想在函数中传递错误的变量类型 (char --> const) 并非如此,因为在片段 2 中也会出现警告。

这是C标准的缺陷;指向 char 数组的指针与指向 const char 数组的指针不兼容,并且可能无法(通过定义的行为)作为指向 const char.

注意,数组自动转换后,print_w(words)传递的是数组指针给print_w,不是数组的数组,而且,数组参数自动调整后,void print_w(const char x[W] [N+1]) 声明 printString 具有指向数组的指针类型的参数,而不是数组的数组。所以我们关心的是数组指针的规则。

对于char (*)[N+1]const char (*)[N+1],我们首先考虑这些指针类型是否兼容。根据 C 2018 6.7.6.1 2,要使两个指针类型兼容,它们必须指向兼容的类型。

它们指向数组,所以我们看 6.7.6.2 6,它说,要使两种数组类型兼容,两者都应具有兼容的元素类型。

对于元素,我们看 6.7.3 11,它说,对于要兼容的两个限定类型,两者都应具有兼容类型的相同限定版本。 charconst char不是全等限定,所以不兼容,所以数组类型不兼容,所以指针类型不兼容。

如果允许对参数类型进行赋值,则函数调用允许传递参数的实参,根据 C 6.5.2.2 2。根据 6.5.16.1 1,赋值允许向 pointed-to 类型“添加”限定符.例如,指向 char 的指针可以分配给指向 const char 的指针。这就是 void printString(const char []) 代码不产生错误或警告消息的原因。但是,规则不允许在类型中更深地添加限定符。因此,指向 char 数组的指针不能分配给指向 const char.

数组的指针

这是C标准中的缺陷。 C 委员会正在做一些工作来解决这个问题。在 draft N2731 中,6.2.5 28 说“……一个数组及其元素类型总是被认为是相同限定的。……”这可以解释指向 char 数组的指针的赋值被分配给指向 charconst 限定数组的指针,这是允许的。

与此同时,当您使用 -pedantic 开关时,GCC 是迂腐的。一种补救措施是不要要求它迂腐。另一种是使用显式强制转换。另一种是使用 Clang 或其他编译器。