一、引言:
若要定义一个变量,可以使用 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:%s age:%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)); //结果为12
printf("%d\n", sizeof(s1)); //结果为12
system("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;
}