繁体   English   中英

如何修复函数及其声明的“冲突类型”?

[英]How to fix “conflicting types” for a function and its declaration?

我想将二维char数组传递给函数,但不知道如何在main()之前声明该函数。 在我声明它之前,该函数可以编译并运行良好。 但是在声明之后,我遇到了编译问题。

我在MacBook Pro上使用EMACS。 编译器是gcc。我试图通过各种方式声明函数打印字符串,包括

void printstring(int, int,char **);

要么

void printstring(int, int,char *); 

但是它们都不起作用。 我的完整代码是:

#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 **不适合,因为它只是指针上的指针。 因此,在2D数组上进行迭代时,字符串的最大尺寸将丢失。

使用标准的前向声明,如果您不想将函数放在主声明之前,则完全复制真实的声明。

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**不能用于指向2D数组,它只能用于指向char*的1D数组的第一个元素,这是其他内容。

您的编译器错误来自于声明和定义不匹配。 正确的代码:

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]) ,它是完全等效的。 但这很难读,所以为什么呢?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM