【问题标题】:assignment to 'int' from 'void *' makes integer from pointer without a cast从 'void *' 对 'int' 的赋值使指针从没有强制转换的整数
【发布时间】:2021-02-08 14:55:46
【问题描述】:

我正在尝试制作一个链表堆栈,并且我按照在线教程进行操作,但是我收到了这个警告,而作者没有。

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

typedef struct stack {
    int data;  
    struct stack *next;

} stack;

stack *top;


void Initialize(stack *s){
    s=malloc(sizeof(stack));
    s->data=NULL;
    s->next=NULL;
    top=s;

    
    return;
}

在调试过程中,如果我没有在初始化函数中使用malloc,则会出现分段错误。 MINGW-W64 编译器。

【问题讨论】:

  • 您似乎遗漏了一些代码。这甚至没有 main,因此我们无法运行此代码来查看您的问题。
  • NULL 通常(但不总是)定义为#define NULL ((void *)0),这将导致赋值s-&gt;data = NULL; 中出现警告,因为s-&gt;data 的类型为int。也许您应该改用s-&gt;data = 0;。另外,您没有显示函数Initialize 是如何被调用的,但是与参数s 对应的参数被函数忽略了。
  • 要么函数Initialize有问题,要么函数参数stack *s没用,应该用局部变量替换。传递给函数的值s 立即被malloc 的结果覆盖。 Initialize 的调用者不会得到修改后的值,因为指针s 是按值传递的。第二个问题:你应该检查malloc的返回值。如果它返回一个NULL指针,那么下面对s-&gt;datas-&gt;next的访问是无效的。
  • 函数参数没有用,因为你将指针分配给全局stack *top;
  • @Sumsar 可见教程的作者是个低素质的程序员。:)

标签: c pointers memory struct


【解决方案1】:

警告是因为NULL 宏被定义为((void *)0)(大多数现代编译器),因为它打算仅用于指针。将此值分配给结构的 data 成员会导致警告。

要删除此警告,请使用 s-&gt;data=0; 代替 s-&gt;data=NULL;。本教程的作者要么使用了较旧的编译器要么禁用了此特定警告。

此外,传递给您的 Initialize 函数的指针 (s) 将是您在调用该函数时用作参数的任何变量的 副本,因此,它的值没有在调用代码中更新。您尚未指定您打算如何使用该功能,但这里有一个(也许)更好的实现:

stack* Initialize(void) { // Don't need an argument - just return the 'answer'
    stack* made = malloc(sizeof(stack));
    if (made) { // Don't attempt the initialization if "malloc" failed!
        made->data = 0;
        made->next = NULL;
    }
    return made;
}

然后,当您调用该函数时,您可以将其返回值分配给您的“全局”top 指针:

//...
top = Initialize();
// You should check that 'top' is not NULL before continuing!

【讨论】:

  • 您可以使用类似:stack *test = Initialize ();,然后在其他检查之前添加 assert(test != NULL)
【解决方案2】:

在 C 中,宏 NULL 的定义类似于

( void * )0

即表达式的类型是void *类型的空指针。

因此在此声明中

s->data=NULL;

将指针分配给int 类型的对象,编译器会发出一条消息,指出您做错了什么。

编写的函数 Initialize 没有意义。除此之外,例如这个声明

s=malloc(sizeof(stack));

不会更改用作函数参数的原始指针top

其实这个函数是多余的。

不过,如果要写这样一个函数,那么它可能看起来像

stack * Initialize( void )
{
    return NULL;
}

并像这样称呼

stack *top = Initialize();

或喜欢

void Initialize( stack **top )
{
    *top = NULL;
}

或者对于一个新创建的节点,它可以像这样声明和定义

void Initialize( stack *s, int data, stack *next )
{
    s->data = data;
    s->next = next;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2011-01-05
    相关资源
    最近更新 更多