c语言 - 为什么当我在函数中传递带有常量参数的 2D 数组时收到警告,而在 1D 中一切正常?



>我有以下两个相似的代码 片段 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*En");
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) :%sn", 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("%cn", str[i]);
}
}

在片段 1 中,我有一个警告告诉我,在第print_w(words);行中:

[警告] 从不兼容的指针类型传递"print_w"的参数 1

暗示我必须在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,赋值允许将限定符"添加"到指向类型。例如,可以将指向char的指针分配给指向const char的指针。这就是void printString(const char [])代码不会产生错误或警告消息的原因。但是,规则不允许在类型中添加更深的限定符。因此,指向char数组的指针不能分配给指向const char数组的指针。

这是 C 标准中的一个缺陷。C委员会有一些工作来解决这个问题。在草案N2731,6.2.5 28中说"......数组及其元素类型始终被认为是相同的限定..."这可以使赋值的解释,即指向char数组的指针被分配给指向const限定的char数组的指针,这是允许的。

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

相关内容

最新更新