如何修复函数及其声明的 "conflicting types"?
How to fix "conflicting types" for a function and its declaration?
我想将一个二维字符数组传递给一个函数,但不知道如何在 main() 之前声明该函数。该函数在我声明它之前编译并运行良好。但是在声明之后,我遇到了编译问题。
我在 MacBook pro 上使用 EMACS。编译器 gcc.I 尝试以各种方式声明我的函数打印字符串,包括
void printstring(int, int,char **);
或
void printstring(int, int,char *);
但其中 none 有效。我的完整代码是:
#include<stdio.h>
#include<stdlib.h>
void printstring(int, int,char **);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
我预计没有编译错误,但我得到了一个错误和一个警告。详情如下:
test.c: In function 'main':
test.c:9:19: warning: passing argument 3 of 'printstring' from incompatible pointer type [-Wincompatible-pointer-types]
printstring(3,6,word);
^~~~
test.c:5:6: note: expected 'char **' but argument is of type 'char (*)[6]'
void printstring(int, int,char **);
^~~~~~~~~~~
test.c: At top level:
test.c:13:6: error: conflicting types for 'printstring'
void printstring(int n, int m, char (*w)[m]){
^~~~~~~~~~~
test.c:5:6: note: previous declaration of 'printstring' was here
void printstring(int, int,char **);
^~~~~~~~~~~
问题是您使用的是可变长度数组。最后一个参数(字符串列表)取决于第二个参数(m
)。而 char **
不合适,因为它只是指针上的指针。因此在二维数组上迭代时,字符串的最大维度将丢失。
使用标准的前向声明,如果您不想将函数放在主函数之前,请完全复制真实的声明。
void printstring(int n, int m, char (*w)[m]);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
如果您有只读字符串,我建议您改用标准常量指针数组:
void printstring(int n, const char *w[]);
int main(){
const char *word[] = {"hello","world","I"};
printstring(3,word);
return 0;
}
void printstring(int n, const char *w[])
{
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
注意
printstring(3,word);
可以替换为
printstring(sizeof(word)/sizeof(word[0]),word);
在数组衰减到指针之前(自动计算字符串的数量)
以下应该有效:
void printstring(int n, int m, char (*w)[m]);
函数原型和定义应该保持相同,除了某些限定符,例如 C++ 中的 const 和默认参数。
如果你出于任何原因想要保持名称自由声明,你可以对可变修改类型使用*
表示法(保留给函数原型范围)
void printstring(int, int,char (*)[*]);
仍然是一个 VLA,事实上,完全等同于使用 m
的符号。尽管从表面上看,它传达的意图可能不像在前向声明中使用 m
那样清楚。
char**
不能用来指向二维数组,它只能用来指向char*
的一维数组的第一个元素,这是另外一回事。
您的编译器错误是由于声明和定义不匹配。正确代码:
void printstring(int n, int m, char w[n][m]);
...
void printstring(int n, int m, char w[n][m]){
...
}
或者,您可以写成void printstring(int n, int m, char (*w)[m])
,这是完全等价的。但这只是更难阅读,那你为什么要这样做?
我想将一个二维字符数组传递给一个函数,但不知道如何在 main() 之前声明该函数。该函数在我声明它之前编译并运行良好。但是在声明之后,我遇到了编译问题。
我在 MacBook pro 上使用 EMACS。编译器 gcc.I 尝试以各种方式声明我的函数打印字符串,包括
void printstring(int, int,char **);
或
void printstring(int, int,char *);
但其中 none 有效。我的完整代码是:
#include<stdio.h>
#include<stdlib.h>
void printstring(int, int,char **);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
我预计没有编译错误,但我得到了一个错误和一个警告。详情如下:
test.c: In function 'main':
test.c:9:19: warning: passing argument 3 of 'printstring' from incompatible pointer type [-Wincompatible-pointer-types]
printstring(3,6,word);
^~~~
test.c:5:6: note: expected 'char **' but argument is of type 'char (*)[6]'
void printstring(int, int,char **);
^~~~~~~~~~~
test.c: At top level:
test.c:13:6: error: conflicting types for 'printstring'
void printstring(int n, int m, char (*w)[m]){
^~~~~~~~~~~
test.c:5:6: note: previous declaration of 'printstring' was here
void printstring(int, int,char **);
^~~~~~~~~~~
问题是您使用的是可变长度数组。最后一个参数(字符串列表)取决于第二个参数(m
)。而 char **
不合适,因为它只是指针上的指针。因此在二维数组上迭代时,字符串的最大维度将丢失。
使用标准的前向声明,如果您不想将函数放在主函数之前,请完全复制真实的声明。
void printstring(int n, int m, char (*w)[m]);
int main(){
char word[3][6]= {"hello","world","I"};
printstring(3,6,word);
return 0;
}
void printstring(int n, int m, char (*w)[m]){
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
如果您有只读字符串,我建议您改用标准常量指针数组:
void printstring(int n, const char *w[]);
int main(){
const char *word[] = {"hello","world","I"};
printstring(3,word);
return 0;
}
void printstring(int n, const char *w[])
{
for (int i = 0; i < n; i++){
printf("%s\n",w[i]);
}
return;
}
注意
printstring(3,word);
可以替换为
printstring(sizeof(word)/sizeof(word[0]),word);
在数组衰减到指针之前(自动计算字符串的数量)
以下应该有效:
void printstring(int n, int m, char (*w)[m]);
函数原型和定义应该保持相同,除了某些限定符,例如 C++ 中的 const 和默认参数。
如果你出于任何原因想要保持名称自由声明,你可以对可变修改类型使用*
表示法(保留给函数原型范围)
void printstring(int, int,char (*)[*]);
仍然是一个 VLA,事实上,完全等同于使用 m
的符号。尽管从表面上看,它传达的意图可能不像在前向声明中使用 m
那样清楚。
char**
不能用来指向二维数组,它只能用来指向char*
的一维数组的第一个元素,这是另外一回事。
您的编译器错误是由于声明和定义不匹配。正确代码:
void printstring(int n, int m, char w[n][m]);
...
void printstring(int n, int m, char w[n][m]){
...
}
或者,您可以写成void printstring(int n, int m, char (*w)[m])
,这是完全等价的。但这只是更难阅读,那你为什么要这样做?