从 'void *' 对 'int' 的赋值使指针从没有强制转换的整数

Posted

技术标签:

【中文标题】从 \'void *\' 对 \'int\' 的赋值使指针从没有强制转换的整数【英文标题】: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 可见教程的作者是个低素质的程序员。:) 【参考方案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;

【讨论】:

以上是关于从 'void *' 对 'int' 的赋值使指针从没有强制转换的整数的主要内容,如果未能解决你的问题,请参考以下文章

C指针和数组:[警告]赋值使指针从整数而不进行强制转换[关闭]

void指针和NULL指针

操作地址

C语言同类型指针赋值简单问题

022.通过指针比较整数大小

void类型详解