在学习C语言的过程中,很多新手会觉得结构体并没有什么卵用,C语言内置的数据类型int呀,double呀已经可以解决我们所碰到的大部分编程问题,然而生活不是编程题,它会给你各种各样用内置数据类型解决不了的难题,这时候就用到了结构体这个神奇的玩意
结构体的定义和初始化
struct stu{
int xuehao;//学号
int score;//分数
char name[10];//名字
}xiaohong = ;//结构体写完需要加分号,因为它虽然有大括号,但它不是一个函数,而是一个数据定义和初始化的过程,像 int x;
上面是一种初始化的方法,还可以这样写
struct stu xiaoming = ;
说到结构体就不得不说typedef
typedef 你可以把它看成是一个命名规则,比如:
typedef struct stu{
int xuehao;
int score;
char name[10];
}STU;
这个时候你初始化或者定义结构体变量就可以这么写:
STU xiaohu = ;
结构体的初始化有一个最大的深坑,几乎每个程序猴都得跳进去一次,这里就来讲一讲这个坑
STU xiaojian ;
xiaojian = ;
相信有很多人会这么写,因为我们见了很多下面的写法
int i;
i = 10;
但是,人家规定结构体跟数组只有定义和初始化在一起的时候才能这么写,否则不行!说到这里聪明的你可能想到了,虽然结构体定义后不能用大括号直接初始化,但是可以像操作数组元素那样进行初始化呀,是的,这就是定义后初始化结构体的唯一方法。在后面会讲结构体成员的引用中会介绍这种方法。
这时候有人就要问了,typedef这玩意设计出来难道就是为了偷个懒?其实偷个懒是其次的,主要功能是用于某一个结构体有多种用途,用typedef可以给结构体起多个名字,比如在一个链表中可以这么写
typedef struct stu{
int xuehao,fenshu;
struct stu *p;
}STU,pSTU;
int main(){
pSTU *point;
STU xiaolong = ;
}
这里的STU和pSTU是一样的,都等于struct stu ,但是为什么要起两个名呢,是因为用处不同,STU所指的是一个链表的节点,而pSTU指的是这个节点的指针域里面存放的一个struct stu 类型的指针,这两个虽然都是struct stu,但是代表的意思是不一样的,就好像你在家里叫狗剩,到了正式场合就不能叫狗剩了,就应该叫杨爱国,赵爱军,宋爱党之类的了
说到这里又涉及到一个指针的问题,C语言中指针是必须指定一个数据类型的,为什么呢,指针就指针类型嘛,还指定什么类型。大错特错,其实在理解上我们不能把指针作为一种数据类型来看。因为我们的电脑系统不是抽象的,它是具体的,它要为每一个变量分配地址,一个指针在我看来有两种属性,第一是它自身的大小,32位系统下一个指针占四个字节,一般等同于一个int变量,第二是它指向的对象的类型(这里用了对象这个词,其实是因为在C++中认为对象是广义的,不光包括java中那种类的实例化,而且包括结构体和基本数据类型),比如:
int *p1;
p1++;
STU *p2;
p2++;
这时候p1与p2在内存上后移的位数就不一样,p1移动4个字节,而p2移动4+4+4=12个字节
正因为他们所指向的对象类型不同,所以指针位移的幅度也不同
好吧,说到这里又涉及到了一个结构体占内存的计算方法.......
简单来说就是结构体占内存不仅仅是按顺序排的,它有一个单位长度的概念,这个单位长度取决于结构体内最大的内置类型,比如上面的结构体,它们的三个成员类型都是4字节,所以占12字节,如果是:
struct str1{
int a;
char b;
int c;
};
这个也是占12字节,虽然char类型只占1字节,但它后面有3个空白位
但如果是:
struct str2{
int a;
char b;
short c;
};
这个结构体,只占8个字节,因为虽然char占1个字节,short占2个字节,但他们加起来没超过4个字节,所以把是short保存在char后面的空白字节中了
讲到这里我们普及一下基本数据类型的占内存空间,C语言只规定了最小的占内存空间,其它的组织或机构可以比这个大,但绝不能比标准的还小。而一般来说各个编译器或者操作系统中,char占1字节,short占2字节,int是4字节(最小2字节),long4字节(最小4字节)。
好了,我们回归正题
结构体的引用
结构体值引用有两种
用“.”来表示引用
int main(){
STU xiaopeng = ;
printf("%d\n",xiaopeng.xuehao);
}
用指针来引用: (*p).xuehao 或 p->xuehao
int main(){
STU *p;
STU xiaoyu = ;
printf("%d\n%d\n",(*p).xuhao,p->score);
}
这时候就可以解决上面那个结构体定义后初始化的问题了,
xiappeng.xuehao = 141092;
(*p).xuehao = 141093;
p->score = 90;
这些都是合法的初始化和赋值方法,但是不要误会,初始化不是赋值,初始化不是赋值,初始化不是赋值,重要的事情要说三遍。