一、引言:
若要定义一个变量,可以使用 C语言提供的基本数据类型(int、char等);如果需要定义多个相同变量(N:1),可以使用数组完成;如果需要定义多个不同变量(N:M),此时 C语言己经无法逐个给出定义,于是放开自定义权限,struct关键字就应运而生了。
二、结构体定义、访问、赋值
请看下面例子:
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct student//定义结构体{char name[100];int age;char sex;int score;}stu;int main(){stu s1;stu *p = &s1;strcpy(s1.name, "ZhangSan");//不能直接赋值s1.age = 19;s1.sex = 'f';s1.score = 98;//若使用键盘输入,%c前留个空格,防止读入回车//scanf("%s%d %c%d", s1.name, &s1.age, &s1.sex, &s1.score);printf("%s\t", s1.name);//点成员运算符printf("%d\t", s1.age);printf("%c\t", s1.sex);printf("%d\n", s1.score);printf("----------------------------------\n");printf("%s\t", p->name);//指向成员运算符printf("%d\t", p->age);printf("%c\t", p->sex);printf("%d\n", p->score);system("pause");return 0;}
注意几个问题:
1、给s1.name不能直接赋值(s1.name = “ZhangSan”;),因为s1.name本质是数组名,是个常量不能赋值。可以使用字符串拷贝的方式。
2、初始化和赋值不同:数组定义时可以初始化(char name[30] = "ZhangSan";合法),定义后不能直接赋值,这是由于初始化使用的是一种特殊语法。
3、两个凡是:凡是基本类型,既可定义时初始化,也可定义后赋值;凡是构造类型,要么在定义时就初始化,不能先定义再以初始化的方式赋值。
三、结构体数组:
本质就是一维数组,其成员是结构体。
结构体嵌套:结构体中,又嵌套结构体。
结构体之间赋值:相同类型结构体变量之间可以赋值,不同类型不可以。
用途:传参和返回(传地址效率高)
typedef struct student {char name[100];int age;}stu;int main(){stu s1 = { { "Jack" }, 20 };stu s2;s2 = s1;//相同类型结构体可以实现互相之间赋值printf("name:%sage:%d\n", s2.name, s2.age);system("pause");return 0;}
四、结构体大小:
由于存在内存对齐,因此结构体实际大小比结构体内所有变量所占内存之和大。
#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct student {int age; //4个字节char sex;//1个字节float score; //8个字节}stu;int main(){stu s1;printf("%d\n", sizeof(stu)); //结果为12printf("%d\n", sizeof(s1));//结果为12system("pause");return 0;}
五、结构体使用注意事项:
1、向结构体内未初始化的指针拷贝。
情形一:name指针没有初始化,并没有指向一个合法的地址
struct student{char *name;//未初始化int score;}stu;int main(){/*可以这样解决:stu.name = (char *)malloc(100);*/strcpy(stu.name,"Jim"); //name 指针并没有指向一个合法的地址stu.score = 99;/*free(stu.name);stu.name = NULL;*/return 0;}
情形二:为指针变量pstu分配了内存,但是同样没有给name指针分配内存。错误与上面第一种情况一样。这里用了一个 malloc给人一种错觉,以为也给name指针分配了内存。
typedef struct student{char *name; //同样未初始化int score;}stu;int main(){stu *pstu;pstu = (stu*)malloc(sizeof(stu)); //给结构体开辟了空间strcpy(pstu->name, "Jimy");pstu->score = 99;free(pstu);return 0;}
2、未释放结构体内指针所指向的空间。
typedef struct student{char*name;int score;}Stu;int main(){Stu * p = (Stu*)malloc(sizeof(Stu));p->name = (char *)malloc(100);strcpy(p->name, "ZhangSan");p->score = 200;free(p->name); //这个地方注意,要由内而外的释放空间free(p);return 0;}