获得;函数的冲突类型“;在C中,为什么?

获得;函数的冲突类型“;在C中,为什么?,c,arrays,C,Arrays,我正在使用以下代码: char dest[5]; char src[5] = "test"; printf("String: %s\n", do_something(dest, src)); char *do_something(char *dest, const char *src) { return dest; } 这里,dou\u something的实现并不重要。 当我尝试编译上述代码时,我得到以下两个异常: 错误:“do_something”(在printf调用时)的类型

我正在使用以下代码:

char dest[5];
char src[5] = "test";

printf("String: %s\n", do_something(dest, src));

char *do_something(char *dest, const char *src)
{
    return dest;
}
这里,
dou\u something
的实现并不重要。 当我尝试编译上述代码时,我得到以下两个异常:

错误:“do_something”(在printf调用时)的类型冲突
错误:前面的“do_something”隐式声明在这里(在原型行)


为什么?

您在使用前没有声明

你需要像这样的东西

char *do_something(char *, const char *);
在printf之前

例如:

#include <stdio.h>
char *do_something(char *, const char *);
char dest[5];
char src[5] = "test";
int main ()
{
printf("String: %s\n", do_something(dest, src));
 return 0;
}

char *do_something(char *dest, const char *src)
{
return dest;
}
#包括
char*做某事(char*,const char*);
char dest[5];
char src[5]=“测试”;
int main()
{
printf(“字符串:%s\n”,do_something(dest,src));
返回0;
}
char*do_某事(char*dest,const char*src)
{
返回目的地;
}

或者,您可以将整个
do\u something
函数放在printf之前。

您试图在声明do\u something之前调用它。您需要在printf行之前添加函数原型:

char* do_something(char*, const char*);

或者,您需要将函数定义移到printf行上方。在函数声明之前,您不能使用它。

您必须在使用函数之前声明它。如果函数名出现在其声明之前,C编译器将遵循某些规则并自行声明。如果它是错误的,你会得到那个错误

您有两个选项:(1)在使用它之前定义它,或者(2)使用不带实现的前向声明。例如:

char *do_something(char *dest, const char *src);

请注意结尾的分号。

如果在使用函数之前没有给出该函数的原型,C会假定它接受任意数量的参数并返回一个int。因此,当您第一次尝试使用do_something时,这就是编译器要找的函数类型。这样做应该会产生关于“隐式函数声明”的警告

因此,在您的例子中,当您稍后实际声明函数时,C不允许函数重载,因此它变得很麻烦,因为您声明了两个具有不同原型但名称相同的函数

简短回答:在尝试使用函数之前先声明它。

在“经典”C语言(C89/90)中,当您调用未声明的函数时,C假定它返回一个
int
,并尝试从实际参数的类型派生其参数的类型(不,它并不像之前有人建议的那样,假设它没有参数)

在您的特定示例中,编译器将查看
do\u something(dest,src)
调用,并隐式派生
do\u something
的声明

int do_something(char *, char *)
但是,在代码的后面,您明确声明
do\u something

char *do_something(char *, const char *)
如您所见,这些声明彼此不同。这是编译器不喜欢的。

C命令3:


确保先声明函数声明中的类型。

/*头文件的开始*/




struct intr\u frame{…};//必须是第一个!




void kill(结构内部框架*);




/*头文件结尾*/
再次观看:

char dest[5];
char src[5] = "test";

printf("String: %s\n", do_something(dest, src));
关注这一行:

printf("String: %s\n", do_something(dest, src));
您可以清楚地看到,do\u something函数没有声明

如果你再看远一点

printf("String: %s\n", do_something(dest, src));

char *do_something(char *dest, const char *src)
{
return dest;
}
您将看到在使用函数后声明函数

您需要使用以下代码修改此部件:

char *do_something(char *dest, const char *src)
{
return dest;
}

printf("String: %s\n", do_something(dest, src));

干杯;)

当您修改c函数定义而忘记更新相应的标题定义时,通常会发生这种情况。

c函数声明背景

在C语言中,函数声明不像在其他语言中那样工作:C编译器本身不会在文件中前后搜索以从调用函数的位置找到函数声明,而且它也不会多次扫描文件以找出关系:编译器只会从上到下精确地向前扫描文件一次。将函数调用连接到函数声明是链接器工作的一部分,并且只有在将文件编译为原始汇编指令后才能完成

这意味着当编译器向前扫描文件时,当编译器第一次遇到函数名时,必须有两种情况之一:要么看到函数声明本身,在这种情况下,编译器确切地知道函数是什么,它以什么类型作为参数,返回什么类型,或者它是对函数的调用,编译器必须猜测函数最终将如何声明

(还有第三种选择,即在函数原型中使用该名称,但我们暂时忽略它,因为如果您首先看到这个问题,您可能没有使用原型。)

历史课

在C语言的早期,编译器必须猜测类型这一事实并不是一个真正的问题:所有的类型或多或少都是相同的——几乎所有的东西都是int或指针,它们的大小都是相同的。(事实上,在C之前的语言B中,根本没有类型;一切都只是一个int或指针,其类型完全由您如何使用它决定!)因此编译器可以根据传递的参数数量安全地猜测任何函数的行为:如果您传递了两个参数,编译器会将两件事推送到调用堆栈上,被调用方可能会声明两个参数,这两个参数都会对齐。如果您只传递了一个参数,但函数期望传递两个参数,那么它仍然可以正常工作,而第二个参数将被忽略/丢弃。如果您传递了三个参数,而函数需要两个参数,那么它仍然可以正常工作,第三个参数将被忽略并由
char *do_something(char *dest, const char *src)
{
return dest;
}

printf("String: %s\n", do_something(dest, src));
int do_something(char arg1[], char arg2[])
{
    ...
}
char *do_something(char *dest, const char *src);