警告:将不兼容的指针类型‘node_t *’赋值给‘struct node_t *’

huangapple go评论60阅读模式
英文:

warning: assignment to ‘struct node_t *’ from incompatible pointer type ‘node_t *

问题

我正在处理一个链表,并尝试将链表中节点(node_t)的信息分配给一个单独的结构体(list_stats_t)。

```c
struct node
{
    char firstName[50], lastName[50], major[50], classStanding[50];
    bday bd;     // 这个结构体只包含日、月和年的整数值

    struct node* next;
};
typedef struct node node_t;

struct stats
{
    // 指向链表中年龄最大和最小的人的节点指针
    struct node_t* oldest;
    struct node_t* youngest;

    // 存储每个月份的生日数量(0 = 一月,11 = 十二月)
    int numBD[12];
};
typedef struct stats list_stats_t;
list_stats_t getListStats(node_t *head)
{
    node_t* temp = head;

    // 创建要返回的对象并将其初始化为链表中的第一个节点
    list_stats_t stat;
    node_t* oldest = temp;
    node_t* youngest = temp;

    while (temp != NULL)  // 遍历链表以查找年龄最大和最小的人
    {
        // 如果当前节点不是最老的,则将最老的设为下一个节点
        if (isOlder(oldest) == false)
            { oldest = temp->next; }
        if (isOlder(youngest) == false)
            { youngest = temp->next; }

        temp = temp->next;      // 下一个值
    }

    // 编译器警告
    stat.oldest = oldest;
    stat.youngest = youngest;

    return stat;
}

我期望在结构体 stats 中的 node_t 值被分配给 getListStats() 函数中的 node_t 值。没有编译错误,只有警告,但我更喜欢避免这些警告。


<details>
<summary>英文:</summary>

I&#39;m working with a linked list and trying to assign information from nodes in a list (node_t) to a separate struct (list_stats_t)

struct node
{
char firstName[50], lastName[50], major[50], classStanding[50];
bday bd; // this struct just contains int values of day, month, and year

struct node* next;

};
typedef struct node node_t;

struct stats
{
// node pointer pointing at the oldest and youngest person in the list
struct node_t* oldest;
struct node_t* youngest;

// holding the number of birthdays in each month (0 = Jan. & 11 = Dec.)
int numBD[12];
}; typedef struct stats list_stats_t;


list_stats_t getListStats(node_t head)
{
node_t
temp = head;

// creates object to be returned and initializes it to the first node in a list
list_stats_t stat;
node_t* oldest = temp;
node_t* youngest = temp;

while (temp != NULL)  // loops through the list to find the oldest and youngest person
{
 // if current node isn&#39;t the oldest, set the oldest to the next node   
    if (isOlder(oldest) == false)
        { oldest = temp-&gt;next; }
    if (isOlder(youngest) == false)
        { youngest = temp-&gt;next; }

    temp = temp-&gt;next;      // next value
}

// compiler warnings
stat.oldest = oldest;
stat.youngest = youngest;

return stat;

}




I was expecting the node_t values in struct stats to be assigned to the node_t values within getListStats(). There aren&#39;t any compiler errors, just warnings but I prefer to avoid those as well

</details>


# 答案1
**得分**: 3

你有两个关于节点类型的名称:

* `struct node`
* `node_t`

`struct node_t` 与这些不同,并不是你打算使用的类型。

<details>
<summary>英文:</summary>

You have two names for your node type:

* `struct node`
* `node_t`

`struct node_t` is different than these, and not the type you intended to use.



</details>



# 答案2
**得分**: 1

编译器消息的来源是`node_t`与`struct node_t`之间的差异,其中`node_t`是一个`typedef`,而不是一个结构标签。

为了解释为什么会出现像"warning: assignment to ‘struct node_t *’ from incompatible pointer type ‘node_t *"这样奇怪的内容:

C语言有不完整类型(incomplete type)的概念,这意味着它允许您在稍后声明类型时使用占位符。一个示例是在`struct node { ... };`声明中的`struct node* next;`。编译器实际上在达到`struct node* next;`时不知道`struct node`是什么 - 这只是一个占位符。一旦编译器在结构声明之后达到最终的`;`,它就知道从那时起`struct node`是什么。

不完整类型/前向声明在各种类似的情况下很有用。虽然我们在编译器知道对象声明之前不能声明不完整类型的对象 - 我们只能声明指向它的指针。

因此,类似`int main (void) { struct bananas* p; }`的东西是有效的C程序,即使没有任何地方存在这样的结构声明 - `p`是指向不完整类型的指针。因此,在编译器发现完整类型之前,我们不能真正使用`p`。

因此,在您的情况中,拼写错误`struct node_t*`创建了一个指向不完整类型的指针,与此时的`struct node`/`node_t`不同,它是一个完整类型。它们是不兼容的类型,因此出现了编译器消息。严格来说,这使得您的程序不符合C语言标准,但编译器选择创建一个非标准的可执行文件。只要给程序员一个有关已发现问题的消息,它可以这样做(如果您想要在类似GCC的编译器中防止这种情况,可以使用`-pedantic-errors`编译)。

<details>
<summary>英文:</summary>

The source of the compiler message is `node_t` vs `struct node_t` where `node_t` is a `typedef`, not a struct tag.

To explain _why_ it would spit out something as strange as &quot;warning: assignment to ‘struct node_t *’ from incompatible pointer type ‘node_t *&quot;:

C has the concept of _incomplete type_, meaning it allows you to use placeholders for a type to be declared later. An example of this is `struct node* next;` inside your `struct node { ... };` declaration. The compiler doesn&#39;t actually know what a `struct node` is by the time it reaches `struct node* next;` - this is just a placeholder. Once the compiler reaches the final `;` after the struct declaration, then it knows what a `struct node` is from there on.

Incomplete type/forward declaration is useful in various similar situations. Although we cannot declare an object of an incomplete type until the compiler knows the object declaration - we can only declare a pointer to one.

Therefore something like `int main (void) { struct bananas* p; }` is a valid C program, even though there&#39;s no such struct declaration present anywhere - `p` is a pointer to an incomplete type. And as such we cannot really use `p` until a complete type has been spotted by the compiler.

So in your case the typo `struct node_t*` created a pointer to an incomplete type, different from `struct node`/`node_t` which at that point is a complete type. They are not compatible types, hence the compiler message. Strictly speaking this made your program invalid C, but the compiler chose to create a non-standard executable anyway. Which it may do as long as it gave the programmer a message about spotted problems. (If you want to prevent that with gcc-like compilers, then compile as `-pedantic-errors`.)

</details>



huangapple
  • 本文由 发表于 2023年3月1日 10:27:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/75599062.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定