结构体中的指针
结构体中可以包含指针成员。一旦结构体中包含了指针成员,那么结构体的赋值运算就会变得复杂一些。请参考本章的10.5节的具体介绍。
typedef struct _student
{
int age;
char sex;
char *name;
}student,*pstudent;
上面的结构体中,name成员是一个字符指针,如果要利用name来表示一个人的名字信息,那么需要单独为name指定内存。
比如:
student s1={30,’M’,”tom”};
上面的定义与初始化结构体变量s1的时候,将s1.name指向了静态常量区中的”tom”字符串首地址。
student s2;
s2.age=25;
s2.sex=’F’;
s2.name=(char *)malloc(16);
strcpy_s(s2.name,16,”susan”);
上面再定义了结构体变量s2之后,为s2.name在堆上分配了16个字节的内存,然后把名字拷贝进内存。
结构体中的指针,可以指向同一个类型的结构体地址。比如下面的定义方法:
typedef struct _node
{
int value;
struct _node *next;
}node,*pnode;
按照这种定义方法,next指针指向了同样类型的结构体地址。这正是数据结构中链表结点的定义方法。
如下图所示,在链表中,链表的头结点中的next指针指向下一个结点,下一个结点中的next指针又指向下下一个结点,最后一个结点的next指针为NULL。这样,只要知道了链表的头结点,就可以将链表中的所有结点遍历一次。
结构体的定义中,经常会出现下面3种不同的成员定义方法:
第一种定义方法中,name[]是一个包含1个元素的字符数组,与length成员一起用来存放一个变长的数据,即在name后面还有length-1个字节的变长数据。此种结构体经常用于存放变长数据。
第二种定义方法中,name[]是一个64个元素的字符数组,因此name[]在结构体中占用的内存空间是定长的。此种结构体用来存放数据的时候,数据不能超过指定的长度,而且容易造成部分内存空间的浪费,
第三种定义方法中,name是一个字符指针,在结构体中占4个字节(X86)或者8个字节(X64),必须为name指定新的内存空间,才能保存相应的数据。
现在我们用3种结构体来存放”lucy Clinton”和78这2个数据,程序示例如下:
#include <string.h>
#include <malloc.h>
typedef struct _INFO1
{
int value;
size_t length;
char name[1];
}INFO1,*PINFO1;
typedef struct _INFO2
{
int value;
char name[64];
}INFO2,*PINFO2;
typedef struct _INFO3
{
int value;
char *name;
}INFO3,*PINFO3;
int _tmain(int argc, _TCHAR* argv[])
{
//计算变长空间大小
INFO1 *pi1 =(INFO1 *)malloc(sizeof(INFO1)+strlen("lucy cliton"));
if(pi1==NULL)
{
return -1;
}
memset(pi1,0,sizeof(INFO1)+strlen("lucy cliton"));
pi1->value=78;
pi1->length = strlen("lucy cliton")+1;
strcpy_s(pi1->name,pi1->length,"lucy cliton");
printf("value:%d,name:%s\n",pi1->value,pi1->name);
free(pi1);
pi1=NULL;
INFO2 *pi2 = (INFO2 *)malloc(sizeof(INFO2));
if(pi2==NULL)
{
return -1;
}
memset(pi2,0,sizeof(INFO2));
pi2->value = 78;
//因为name是定长的64个字节,在存放”lucy clinton”的时候
//有部分空间被浪费了。
strcpy_s(pi2->name,64,"lucy cliton");
printf("value:%d,name:%s\n",pi2->value,pi2->name);
free(pi2);
pi2 = NULL;
INFO3 *pi3 = (INFO3*)malloc(sizeof(INFO3));
if(pi3==NULL)
{
return -1;
}
memset(pi3,0,sizeof(INFO3));
pi3->value = 78;
//需要为name指定新的内存空间,这里从堆上分配
pi3->name = (char *)malloc(strlen("lucy cliton")+1);
if(pi3->name ==NULL)
{
free(pi3);
return -1;
}
memset(pi3->name,0,strlen("lucy cliton")+1);
strcpy_s(pi3->name,strlen("lucy cliton")+1,
"lucy cliton");
printf("value:%d,name:%s\n",pi3->value,pi3->name);
free(pi3->name);
free(pi3);
pi3=NULL;
return 0;
}