自己执行“strcpy”(C)不起作用!冲突的类型。为什么?

时间:2013-12-07 17:18:46

标签: c implicit-declaration

我的大学建议我从本文档中学习C作为Java - 程序员:“C for Java Programmers”来自J. Maassen。

在第46页(PDF-第47页),Maassen尝试实施他自己的C strcpy函数版本,名为my_strcpy

char *my_strcpy(char *destination, char *source)
{
    char*p = destination;
    while (*source != '\0')
    {
        *p++ = *source++;
    }
    *p = '\0';
    return destination;
}

我试图用这个功能编写一个程序 请参阅第45页(PDF-第46页)。在这里,Maassen推出了他的第一个strcpy方法版本。他包含stdio.h并将strA复制到strB

所以,以下程序应该有效,不应该吗?

#include <stdio.h>

char strA[80] = "A string to be used for demonstration purposes";
char strB[80];

int main(void)
{
    my_strcpy(strB, strA);
    puts(strB);
}

char *my_strcpy(char *destination, char *source)
{
    char*p = destination;
    while (*source != '\0')
    {
        *p++ = *source++;
    }
    *p = '\0';
    return destination;
}

嗯,实际上并非如此 因为每次我编译这个程序时,都会出现以下错误:

PROGRAM.c:12:7: error: conflicting types for ‘my_strcpy’
 char *my_strcpy(char *destination, char *source)
       ^
PROGRAM.c:8:5: note: previous implicit declaration of ‘my_strcpy’ was here
 mystrcpy(strB, strA);
 ^

为什么这个程序不起作用?我的意思是,它应该有效,不应该吗? 我已经看到了strcpy函数here的类似实现。那个实现也不起作用!我得到了同样的错误!

怎么了?

3 个答案:

答案 0 :(得分:3)

当编译器看到程序的第8行时,它不知道my_strcpy采用或返回的类型。可以在源文件中切换mainmy_strcpy的顺序,也可以在my_strcpy之前添加main的原型。

答案 1 :(得分:2)

与Java在文本声明之前可以使用的方法不同,C需要为您调用的每个函数设置原型。如果您不提供原型,C使用默认规则,要求无原型函数获取与您第一次传递的任何类型相匹配的参数,并返回int

要解决此问题,请在main之前添加此行:

char *my_strcpy(char *, char *);

注意:真实strcpy允许将常量指针作为第二个参数传递。这可以让你像这样打电话:

my_strcpy(dest, "quick brown fox");

我建议你更改声明和定义如下:

char *my_strcpy(char *, const char *);

char *my_strcpy(char *destination, const char *source)
{
      char* p = destination;
      while (*source != '\0')
      {
          *p++ = *source++;
      }
      *p = '\0';
     return destination;
}

另一点需要注意的是,您可以使用destinationsource完成相同的操作,避免使用p。您还可以使用隐含的比较为零 - 另一个在Java中不可用的东西:

char *my_strcpy(char *destination, const char *source)
{
      while (*source) // Removed comparison to zero
      {
          *destination++ = *source++;
      }
      *destination = '\0';
     return destination;
}

最后,为了避免在循环结束时分配零,你可以选择一个无体的单线程实现:

char *my_strcpy(char *destination, const char *source)
{
      while (*destination++ = *source++)
          ;
     return destination;
}

答案 2 :(得分:1)

第一次使用my_strcpy时,编译器还没有看到它,并且没有原型。所以它(可能)自动将其定义为返回int的函数。

您需要在通话前提供原型:

char *my_strcpy(char *destination, char *source);

int main(void)
{
    my_strcpy(strB, strA);
    puts(strB);
}

char *my_strcpy(char *destination, char *source)
{
    ...

或在实际调用之前定义调用(即将main()放在底部)。

对于大型项目,您可以将所有原型放在外部文件中,然后包含:

#include "my_functions.h"

BTW,main通常是从命令行传递的参数,因此您可以将其定义为

int main(int argc, char **argv) {


    return 0;
}

返回有效的返回码(如果一切顺利,则为0)。您可以使用* pragma * s告诉编译器在被调用代码中不需要某些参数。