C语言之结构体

C语言中,结构体是一种很常用的数据类型。简单而又复杂,能够用好它实属不易。下面总结下它的常见用法及容易出错的地方。

一、关于结构体的声明

1、匿名声明。如:

struct {

   int i,j;

}point;

说明:

>>这段代码的含义是,声明一个无名(anonymous)的结构体,并创建了一个结构体变量point。如果这段声明是放在全局域(在任意函数(比如main函数)外)内,那么point内的变量将被初始化为默认值,换句话说,以这种方式声明结构体变量时就已经为它分配了内存空间。

>>适用于该结构体只需要产生一个变量!本例中,该匿名结构体将有且仅有point这个结构体变量!

>>不同的匿名结构体变量,类型是不同的!如

struct {

   int i,j;

}p1,p2;


struct {

   int i,j;

}p3;

>>如果将 p1=p2 ,则ok;如果将 p1=p3 ,则编译器提示"incompatible types when assigning to type ‘struct <anonymous>’ from type ‘struct <anonymous>’",两者的实际类型是不一样的。

2、显式声明一个结构体

struct node{

   int i,j;

};

>> 声明了一个结构体 struct node,如果需要声明一个它的对象,则可以这样:struct node n1;

>> 可以声明多个该结构体的变量。

>> 区别"C中的结构体变量" 和 "Java中的类对象"。C中,"struct node n1;"创建了一个结构体变量,并为它分配了内存空间,不一定初始化!得看这个变量是否在全局域;而Java中,"Node n1;"只是声明了一个类对象,也就是说是一个"空引用",可以想象成C中的空指针,当"n1 = new Node();"时,n1才指向了该对象的内存空间。因此,在Java中,可以通过"n1==null"来判断对象是否为空;在C中,不能通过"n1==NULL"来判断,因为"n1"并不是一个指针,而是一个类型变量的名字,就像"int a;"这种,显然"a"不是指针!

3、用typedef来简化结构体的写法

typedefstruct {

   int i,j;

}Node;

>>相当于把红色代码该名为Node了。以前需要这样声明"struct node n1;",现在只需要"Node n1;"

>>这段代码中,如果没有typedef,代码的意思是"声明了一个匿名结构体变量"!注意区别。

4、在结构体中声明结构体变量

typedef struct {

   int i,j;

   Node n1;

}Node;

>>这段代码是错误的!

>>错误1:直接在结构体中声明另外一个结构体,会出现死循环,如A包括B,B又包括A,A又包括B……使得编译器无法知道结构体的空间大小,因此,无法通过编译!

>>错误2:typedef还没有将结构体命名为Node,你就在结构体中使用了Node,显然,编译器此时还不知到Node是什么!所以,无法通过编译!

>>正确的使用方法如下:

typedef struct node{

   int i,j;

   struct node *n1;

}Node;


二、关于结构体的赋值

1、声明一个变量后的默认值

typedef struct {

   char *p;

   int i;

   char ch[256];

}mystr;

mystr str;//声明一个变量,此时已为之分配了空间!

>>如前面提到的,如果这个变量声明是在全局,则"str.p等于NULL,str.i等于0,str.ch数组都是'\0'",为默认初始值;如果不在全局,则所有值都是"野值"。

2、手动初始化

mystr str2={"abc",2,"def"};

mystr str3={.p="abc",.ch="def"};

mystr str4={.ch[256]="def"};//error!

mystr str5={.ch[10]="def"};//right!

>>此时,str2声明时手动赋了初值。str2.p和str2.ch赋值时的行为是不一样的!str2.p是一个字符指针,也就是将p指向常量字符串"abc"在内存中的地址;而str2.ch是一个常量字符指针(无法操作指针),代表的是字符数组,也就是将常量字符串"def"逐字符copy到ch数组里,赋值结束后,ch的值是:'d','e','f','\0','\0'……

>>也可以像str3这样初始化结构体中的某些变量,值得注意的是str4和str5。对于数组(如 char a[size])来说,传递给常量字符指针,可以是"a",可以是"a[n]"(0<=n<size,编译器会忽略掉n),不能是"a[size]"(编译器会检测,报"array index in initializer exceeds array bounds")。

3、赋值

mystr str6;

str6.p = "abc";

或者

mystr * pstr = & str6;//得到这个结构体变量的指针

pstr->p = "abc";

4、动态生成结构体变量

mystr * pstr = (mystr*)malloc(sizeof(mystr));

pstr->p = "abc";

>>注意,如果是动态生成的结构体变量(用到了malloc),则必须在丢弃该变量前将他的内存空间释放掉(用free)。

>>如果结构体内部也存在动态生成的对象,在释放结构体之前要先释放掉其内部的内存空间,如下

pstr->p = (char*)malloc(sizeof(char)*256);

free(pstr->p);

free(pstr);

注:本文版权所有,如有转载,请链接本文地址blog.csdn.net/whuslei


  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值