对于以下C代码(用于交换两个数字),我收到swap
函数的“冲突类型”错误:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a,b;
printf("enter the numbers to be swapped");
scanf("%d%d",&a,&b);
printf("before swap");
printf("a=%d,b=%d",a,b);
swap(&a,&b,sizeof(int));
printf("after swap");
printf("a=%d,b=%d",a,b);
getch();
}
void swap(void *p1,void *p2,int size)
{
char buffer[size];
memcpy(buffer,p1,size);
memcpy(p1,p2,size);
memcpy(p2,buffer,size);
return(0);
}
编译器诊断:
<source>:10:6: warning: implicit declaration of function 'swap' [-Wimplicit-function-declaration]
swap(&a,&b,sizeof(int));
^~~~
program:15:6: warning: conflicting types for 'swap'
void swap(void *p1,void *p2,int size)
^~~~
有人能说出为什么会出现这个错误吗?
解决方法是什么?
答案 0 :(得分:15)
问题是swap
在使用之前未声明。因此,它被分配了一个“默认签名”,在这种情况下,它将与其实际签名不匹配。引用Andrey T:
参数通过集合传递 严格定义的转换。
int *
指针将作为int *
传递 例如,指针。换一种说法, 参数类型是暂时的 从论证类型中“推导出”。只要 返回类型假定为int
。
除此之外,您的代码会产生许多其他警告。如果使用gcc
,请使用-Wall -pedantic
(或甚至使用-Wextra
)进行编译,并确保在继续编写其他功能之前修复每个警告。此外,您可能想告诉编译器您是在编写ANSI C(-ansi
)还是C99(-std=c99
)。
一些评论:
main
返回int
。
return 0
或return EXIT_SUCCESS
。getch
:#include <curses.h>
的定义。
getchar
。memcpy
的定义:#include <string.h>
。您可能希望使用void
来分配可变大小的缓冲区。这也适用于较旧的编译器:
malloc
答案 1 :(得分:3)
您需要在使用之前声明交换。例如,将swap
放在main之上,或者为swap
添加原型,如下所示:
void swap(void *,void *,int);
int main ()
顺便说一下,main
应该int
而不是void
,并且通常会返回零值,除非出现错误。
答案 2 :(得分:3)
首先,实际的错误信息不会受到伤害。
其次,使[size]的缓冲区仅适用于某些编译器(这是一个新功能,并非所有编译器都有它)。你确定你的吗?
第三,你需要在调用之前声明swap。在文件顶部添加原型:
void swap(void *p1,void *p2,int size);
答案 3 :(得分:2)
您未能明确声明swap
,迫使编译器在调用时对函数进行假设。根据C规则,编译器将假定swap
是
int swap(int *, int *, size_t)
稍后您将交换声明为
void swap(void *, void *, int)
这与编译器假设的明显不同。这是编译器告诉你的冲突。
此外,您的void swap
尝试return 0
。那你想要达到什么目的?
P.S。它是int main
,而不是void main
。
P.P.S。如果程序的输出不以换行符结尾,则不保证程序产生任何输出。
答案 4 :(得分:1)
你可能想知道为什么程序在没有swap()原型的情况下编译,这是因为编译器不仅仅是一个C99工具。它还编译C89和K&amp; R C程序。
C89添加了原型。在C89之前,编译器不需要查看函数的声明(原型),除非它返回int
之外的其他内容,并且编译器根本不知道形式参数的类型。编译器只使用实际参数的类型调用每个函数,它们接收一组默认参数提升以简化操作。程序员将运行lint
实用程序来交叉检查实际和形式参数。该程序仍附带BSD发行版。
K&amp; R程序及其相应的代码样式仍然被编译器接受,因此当它看到一个没有原型可用的函数时,它就会继续调用它。
在这种情况下,您可以在调用和函数定义之间切换范例。编译器在必须生成调用时对未声明函数所做的K&amp; R C假设结果证明无效。即使您已经用K&amp; R风格编写了整个程序,编译器在发现函数参数的真实类型时也会提出同样的抱怨。
答案 5 :(得分:0)
GCC,这是一个警告,
当你在使用它之前没有声明一个函数时,编译器会尝试使用对该函数的调用类型来猜测声明。对行为进行处理。
答案 6 :(得分:-1)
好吧,它在http://codepad.org上编译(删除getch()
后,这是无关紧要的)。也许你的编译器抱怨在非限制指针上使用memcpy?
swap()
p1
和p2
不保证不是别名。这是一个等待发生的实际错误 - 在&a[i]
时调用&a[j]
和memcpy
上的调用可能会导致i==j
。使用memmove
(保证不会在重叠区域爆炸)或声明指针restricted
。