在C语言里面声明指针并用malloc赋值与与直接声明变量并获取其指针有何区别?

比如说Link是链表结构体,
那Link n; &n
与Link *n, n=malloc(sizeof(Link))有无区别?
请各位再看一下问题补充,不需要回答什么堆或者栈的详细内部实现,只需要说对于初级程序员来说,假如只需要做一般的链表创建、插入、删除操作,两者的运行效果上有无区别,如果有,有何区别?
根据对追问的回答来采纳!
最新回答
静若幽兰

2024-05-14 02:38:57

区别是有的,直接声明的变量存储在连续的内存区域上,比如char a[5];char b[5];你可以用gets(a)输入10个字符;使用malloc分配的内存区域不一定是连续(很大程度上不是连续的),他们是一块一块的内存区域,使用链表联系在一起。
直接声明的变量储存的区域叫做 栈(stack),使用malloc获得的区域叫堆(heap)。

栈是连续高速而小的(1M,2M的都有,一般不超过2M),堆是不连续低速但容量极大的。
追问
对初学者来说,如果只看很基本的插入、删除等操作,程序运行结果上有无区别?
追答
如果是链表的操作的话,那么没有任何区别,因为一个节点里面有指向下一个节点的地址,只要有这个地址,就能确定一个内存区域。

struct linklist
{
...//数据
struct linklist *pNext;//这个用于指向下一个结构体,不需要数组一样的连续内存区域
}
病系少女

2024-05-14 05:12:26

当然有了。
Link
{
Link *next;//指向下个节点
Elem e;//元素
}
Link n;就是创建一个Link的结构体,这个变量叫做n。&n表示Link结构体n的首地址。
但是因为Link是链表,里面有个成员是指向一个结构体的指针。所以要用malloc分配空间,而malloc(sizeof(Link));就是为这个地址分配一个可用的堆空间。
你可以开始定义一个 Link L;但是L.next是指针,还是要用malloc为其分配空间。
因为这样是不行。这样定的话会是一个死递归,是非法的。
Link
{
Link next;
Elem e;//元素
}
追问
我试过不需要再分配都可以用next。
追答
那是一个地址,但是没有空间。如果不用malloc你试试:
Link l;
l.next->e根本放不进去东西的,程序会退出的。l.next是在Link l;时就分配好的指针变量,地址还没确定呢。
追问
可以放的,就用你上面的代码。
追答

vc6.0反正是不行。有图有真相。

追问
可是我说的是当前这个节点,你再声明一个Link nextL,刚刚那个s.next=L,再L.p="hello"不就行了?
追答
行啊,但是这样做你就是要创建很多结构体变量了,而且各个还是独立的。如果你这个nextL.next还要放呢,你是不是还要搞个nextnextL的变量?这就不灵活了。
追问
node *tail;
tail=(node*)malloc(sizeof(node));
tail->v=20000;
tail->next=NULL;
q->next=tail;

node tail;
tail.v=20000;
tail.next=NULL;
q->next=&tail;
功能是在末尾追加一个节点,下面的报错,你说是为什么?
追答
都行的啊。你的q有没malloc?
追问
编译是没错,但是在遍历输出的时候,使用下面的情况下,输出完最后一个似乎还有个next,然后就报错了。
追答
有问题还是贴代码吧,应该没有什么疑问了吧?
追问
贴不下,你上面实际上并没有说出这两者的区别,不过如果你解释了上面我的代码为什么报错就采纳你。代码已经贴了,q就是尾节点,输出是标准的输出函数。
追答
你的代码都不完全。出错的原因不好解释。区别就是malloc灵活,无用定义无数个变量。你的这种方式可以,但是要定义多个变量,然后连到一起。
追问
那你就定义一个标准的结构体,初始化一下,然后用我上面两种方式添加个尾节点再遍历输出试试。
追答
#include "stdio.h"

#include "stdlib.h"

struct Link

{

 char *p;

 struct Link *next;

};

struct Link2

{

 short p;

 struct Link2 *next;

};

int main()

{

 //你的做法

 struct Link l,a,b,c;

 l.next=&a;

 a.next=&b;

 b.next=&c;

 l.p="hello ";

 a.p="world ";

 b.p="HI ";

 c.p="C ";

 printf("%s%s%s%s\n",l.p,a.p,b.p,c.p);

 //标准的做法

 int i=0;

 struct Link2 head,*t;

 t=(struct Link2 *)malloc(sizeof(struct Link2));

 t=&head;

 while (i<10)

 {

  t->p=i;

  t->next=(struct Link2*)malloc(sizeof(struct Link2));

  t=t->next;

  i++;

 }

 t->next=NULL;

 printf("created\n");

 t=&head;

 i=0;

 while(t->next!=NULL)

 {

  printf("%d\n",t->p);

  t=t->next;

 }

 return 0;

}
吃糖不吃苦

2024-05-14 05:59:51

区别在于&n是个局部静态的指针,是在栈中。malloc分配的是动态的,分配在堆区中。
C程序中编译后的程序在加载后,栈中分配局部变量空间,堆区是向上增长的用于分配程序员申请的内存空间。如果你在一个函数中一下子分配一个很大的数据,就可能导致栈溢出。
另外malloc用于分配大小不固定的链表,使用变量静态分配的不够灵活。
追问
对初学者来说,如果只看很基本的插入、删除等操作,程序运行结果上有无区别?
追答
在结果上无区别。只是写代码的时候一个用“->”访问结构体内成员,一个用"."访问结构体内成员。除非对直接声明变量获取的指针再复制给一个指针变量。
追问
在对@爱问西瓜爱答树的答案的追问中,我的代码有个奇怪的报错,你认为是什么原因?
追答
没看到你的完整代码,也不清楚报错信息是什么,不好判定原因。
叶舞霓裳

2024-05-14 03:34:41

首先你得明白malloc函数的作用;malloc函数是在内存中找到一个合适大小的内存空间来存储数据,并让指针指向这个空间的首地址。它的意义是在创建数组时,可以创建动态数组。
比如 int a[n],*p;p=a;是不合法的。而int *p;p=(int *)malloc(n*sizeof(int))却可以实现创建这样一个长度为n的数组
听萧与声

2024-05-14 05:14:26

区别当然是有的
Link n; 申明结构体实体
&n 结构体地址

Link *n; 申明结构体指针
n=malloc(sizeof(Link)); 让结构体指针指向申请的内存空间,需要free释放

后者需要释放并且申请大小灵活
希望对你有帮助
追问
要用malloc,多个函数反而还更灵活了?是更复杂了吧!
追答
是分配的时候更灵活了,当然可以理解为使用更复杂