C/C++高手进,关于声明结构体变量的两种方式区别以及NULL指针是否要显示指定的问题。

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

struct node
{
int v;
struct node *next;
};

void printAll(node *head)
{
node *p;
p=head;
while(p)
{
printf("%d\t",p->v);
p=p->next;
}
printf("\n");
}

int main(int argc, char* argv[])
{
node *head;
head=(node*)malloc(sizeof(node));
head->v=0;
//1.下面这两种添加尾节点的方法有何区别或者利弊?
//2.尾节点的NULL指针是否应该显式指定?默认的不是NULL?
/*
node *n1;
n1=(node*)malloc(sizeof(node));
n1->v=1;
n1->next=NULL;

head->next=n1;
*/

node n1;
n1.v=1;
n1.next=NULL;
head->next=&n1;

printAll(head);
system("pause");
return 0;
}

一个是动态分配的方法,一个局部实例的方法,前者分配的对象空间在堆里面,
生命周期是全局的,但最后需要主动释放空间。后者使用简单,不用考虑对象
释放的问题,但由于变量是局部的,生命周期仅在函数内部,可能会因为提前
析构而产生意外的结果,另外一个局部对象分配的内存在堆栈里面,会受堆栈
大小的影响可能有堆栈溢出的危险。

尾结点的指针应该显式指定NULL,否则就是一个潜在风险,因为编译器不会
保证为局部变量(及结构体)进行初始化。追问

请修改上面我的代码,用局部变量的方式,使其造成你上面说的“意外的结果”或者“溢出的危险”。

追答

想要堆栈溢出很容易:
struct node
{ int v[1024];
struct node *next;
};

void main()
{ int i;
node nd[10240];
for(i=0;i<10240;i++)
{ nd[i].v[0]=0;
}
}
运行时直接堆栈溢出。
如果nd[10240]改成内存分配方式就不会溢出。

追问

你这个结构体的结构比我定义那个复杂多了,根据你的代码确实报错了,是堆栈溢出,那请问你应该怎么修改成malloc的格式呢?麻烦你再贴一下代码吧。

追答

不建议用malloc, 还是用new吧。

struct node
{ int v[1024];
struct node *next;
};

void main()
{ int i;
node *nd=new node[10240];
for(i=0;i<10240;i++)
{ nd[i].v[0]=0;
}
delete[] node;
}

追问

c语言咋写啊,new是c++的了。

追答

C的话:
struct node *nd=(node *)malloc(10240*sizeof(node));

追问

不好意思,我太菜了,你能不能把main里面的用malloc全部写一下?我这边不知道怎么改。

追答

void main()
{ int i;
struct node *nd=(node *)malloc(10240*sizeof(node));
for(i=0;i<10240;i++)
{ nd[i].v[0]=0;
}
free(nd);
}

温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-11-07

    如同tmduser所说 ,方法一内存是c运行库向系统申请的一段静态地址 ,你不用free的话可以一直使用 ,但是已经不用且没有free就会造成内存溢出直至进程结束 ,方法二是在函数里声明的变量 ,则它只在函数运行时存在 ,在函数返回时释放 ,由于它是处于栈堆里的 ,若当函数是返回你还在使用 ,也许就会修改到正在执行的函数里所声明的变量的值

    不管是声明的变量(栈堆)或是申请的内存(malloc) ,编译器都不会对其进行初始化 ,也就是说如果刚才栈堆或者malloc申请的内存里面的数据不全为0 ,则将会导致尾节点的next值不为NULL ,这将会导致错误的内存访问

第2个回答  2013-11-07
楼上说的比较清楚了:
我补充说一下:
先说明你的node没typedef需要用struct node 才算做完整类型;

malloc()是动态申请内存空间,分配的内存空间在程序运行空间的队上,这种使用需要注意两点:
1,申请后需要判断是否申请成功,例如上面的n1=(node*)malloc(sizeof(node));后要判断n1是否为NULL;
2,申请成功的空间使用完成需要手动释放:free()
要产生上面溢出危险很容易,在一个函数里for循环2的31次申请会死机的

其实你就把struct node看成一个和int相似的类型罢了,一个是自定义类型,Int是内置类型;不一样的就是他们的操作,也就是所谓的方法;自定义类型需要你自己定义操作,int这种内置类型有内置的+,-,*,/等操作;就像你定义一个int a;和int *pi;一样pi这里没初始化时不知道指向哪里,a没初始化不知道什么值;你定义的struct node *n;也不知指向哪里,当然它里面的指针类型变量next和其他的的变量一样也不知道指向哪里,所以你要显示初始化为NULL,当然如果是c++一般会有构造函数,就是做这些事情的追问

你上面说的危险是内存不足的危险吧,与我提问是两回事。

相似回答