在C语言中将结构体传递给函数时出现错误

3
当我将一个结构体传递给一个函数时,出现了错误:预期为“struct book”,但参数类型为“struct book”。为什么会这样?
#include <stdio.h>
#include <string.h>

struct book
{
    int id;
    char title[50];
};

int showBooks(struct book x);

int main()
{
    struct book
    {
        int id;
        char title[50];
    };

    struct book book1,book2;

    book1.id = 2;
    book2.id = 3;

    strcpy(book1.title, "c programming");
    strcpy(book2.title, "libc refrence");

    printf("Book\t\tID\n");

    showBooks(book1);
    showBooks(book2);
}

int showBooks(struct book x)
{
    printf("%s\t%d\n", x.title, x.id);
}

错误信息如下:

错误:

30:12:错误:‘showBooks’的参数1类型不兼容
showBooks(book1);

10:5:注意:期望的是‘struct book’类型,但实参是‘struct book’类型 int showBooks(struct book x);

31:12:错误:‘showBooks’的参数1类型不兼容
showBooks(book2);

10:5:注意:期望的是‘struct book’类型,但实参是‘struct book’类型 int showBooks(struct book x);

这里出了什么问题?


你正在使用什么编译器? - chux - Reinstate Monica
gcc版本6.3.0 - lab0
5
为什么你有两个“book”的定义?删除主体内的一个。 - Retired Ninja
与书的重新定义无关,showBooks()函数应返回void。 - jarmod
哈哈,我喜欢这样的错误消息(其实不是)。编译器应该更明显地表明名称可能相同但类型记录不同。用户看到这样的错误消息会认为编译器喝醉了酒:) - Martin James
2个回答

5
您的两个不同的结构定义定义了两种不同的类型。虽然它们都被称为struct book,但它们并不是相同的类型。
您的变量book1book2具有本地结构的类型,但函数需要全局结构的类型,因此会出现错误。
您可以通过删除本地结构定义来解决问题;然后book1将具有全局结构的类型等。

6
恭喜达成10万个关注者! - Jonathan Leffler
@JonathanLeffler 仍在学习中... 在检查有关此答案的标准时,我发现一个TU中的本地结构体可以与另一个TU中的全局结构体兼容(因此,另一个TU中的 struct book 可以与此代码中的两个 struct book 兼容,即使这两个结构体彼此不兼容!)。 - M.M
交叉TU结构兼容性规则非常有趣,而且在考虑时至关重要。问题在于,“内部”结构与“外部”结构之间的区别仅仅是通过新定义来实现的(尽管函数中的“struct book;”也会隐藏“外部”定义)。 - Jonathan Leffler
@JonathanLeffler 所以如果我们通过另一个翻译单元中的函数进行传递,实际上可以将 book1 传递给 showBooks - M.M
我认为你不是有意要逃避它,但在实践中你可能会这样做。主要规则在C11 [§6.2.7 兼容类型和复合类型 ¶1](http://port70.net/~nsz/c/c11/n1570.html#6.2.7)和[§6.7.2 类型说明符](http://port70.net/~nsz/c/c11/n1570.html#6.7.2),特别是[§6.7.2.1 结构和联合说明符](http://port70.net/~nsz/c/c11/n1570.html#6.7.2.1)。你会在哪里声明外部函数原型?它将使用其中的一种类型,而另一种类型不同。然而,我怀疑编译器很少会去寻找这种欺骗行为。 - Jonathan Leffler

3
一个隐藏了同名全局变量的本地变量或参数。这可能会引起混淆。在 main() 中的 "struct book" 隐藏了全局定义的 "struct book"。 变量 book1 和 book2 是带有对 main() 的局部引用的类型为 "struct book"。 showBooks() 使用 book1 或 book2 作为形式参数。 实际参数使用全局定义的 "struct book",导致不兼容的类型。 注释掉本地定义并查看差异。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接