如何解决C中的“冲突类型错误”?

时间:2009-11-22 17:33:03

标签: c

对于以下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)
     ^~~~

有人能说出为什么会出现这个错误吗?

解决方法是什么?

7 个答案:

答案 0 :(得分:15)

问题是swap在使用之前未声明。因此,它被分配了一个“默认签名”,在这种情况下,它将与其实际签名不匹配。引用Andrey T

  

参数通过集合传递   严格定义的转换。 int *   指针将作为int *传递   例如,指针。换一种说法,   参数类型是暂时的   从论证类型中“推导出”。只要   返回类型假定为int

除此之外,您的代码会产生许多其他警告。如果使用gcc,请使用-Wall -pedantic(或甚至使用-Wextra)进行编译,并确保在继续编写其他功能之前修复每个警告。此外,您可能想告诉编译器您是在编写ANSI C(-ansi)还是C99(-std=c99)。

一些评论:

  • 在逗号后加上空格。
  • main返回int
    • 并将其设为return 0return EXIT_SUCCESS
  • 导入getch#include <curses.h>的定义。
  • 导入memcpy的定义:#include <string.h>
  • 请勿在{{1​​}}函数中返回内容。
  • 您可能希望使用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() p1p2不保证不是别名。这是一个等待发生的实际错误 - 在&a[i]时调用&a[j]memcpy上的调用可能会导致i==j。使用memmove(保证不会在重叠区域爆炸)或声明指针restricted