好久不看C语言的书了,许多名词与以前也不一样了。以前小雅的老师把现在要讲的这一章叫“结构体”,现在的新书上叫“构造体”,小雅比较怀旧,仍称之为“结构体”。
结构体就是将几个类型的数据结合成一个类型的数据来处理,例如图书馆管理书籍,一本书总是包含编号、书名、单价等内容,于是把编号、书名、单价结合成一个类型,当然这样的数据类型是自定义的数据类型,这就是结构体。注意:结构体是数据类型,而不是变量,必须在程序中定义了该类型的就是后才能操作数据。
结构体的使用要注意以下几个方面:
![]()
#include<stdio.h>#include<string.h> //结构体的定义structBOOK {charid[4]; //编号charname[64]; //书名floatprice; //单价 };intmain(void) { //结构体也可以初始化时直接赋值structBOOK clang = {"101", "劝学网的C语言教程", 25.5};structBOOK books[2];structBOOK *p; //变量或数组对结构体元素的赋值 strcpy(books[0].id, "201"); strcpy(books[0].name, "劝学网的Oracle教程"); books[0].price = 35.5; //指针对结构体元素的赋值 p = books + 1; strcpy(p->id, "202"); strcpy(p->name, "小雅的Java教程"); p->price = 45.5; //显示结构体变量的内容 printf("%s, %s, %f\n", clang.id, clang.name, clang.price); printf("%s, %s, %f\n", books[0].id, books[0].name, books[0].price); printf("%s, %s, %f\n", p->id, books[1].name, (books+1)->price);return0; }
下面例子分别演示结构体变量、指针在作参数和返回值时的各种情况。
![]()
#include<stdio.h>#include<stdlib.h>#include<string.h>structp_type {charid[4]; //编码charname[16]; //姓名 }; //结构体变量作参数 void setByVar(structp_type per) { strcpy(per.id, "202"); strcpy(per.name, "张展");return; } //结构体指针作参数 void setByAdd(structp_type *per) { strcpy(per->id , "303"); strcpy(per->name, "张腾");return; } //结构体变量作返回值structp_type setNewByVar() { staticstructp_type zh; //一定要是静态变量才能作为返回值 strcpy(zh.id, "404"); strcpy(zh.name, "张翅");returnzh; } //结构体指针作返回值structp_type *setNewByAdd() {structp_type *p; p = (structp_type *)malloc(sizeof(structp_type)); strcpy(p->id, "505"); strcpy(p->name, "张去");returnp; }voidprint(const structp_type *per) { printf("%s, %s\n", per->id, per->name);return}intmain(void) {structp_type zhang, *p, tmp; //变量中的初始值 strcpy(zhang.id, "101"); strcpy(zhang.name, "张飞"); //用变量直接作参数,值不能被修改 setByVar(zhang); print(&zhang); //结果:101, 张飞 //用指针直接作参数,值可以被修改 setByAdd(&zhang); print(&zhang); //结果:303, 张腾 //用变量直接作返回值,OK tmp = setNewByVar(); print(&tmp); //结果:404, 张翅 //用指针直接作返回值,OK p = setNewByAdd(); print(p); //结果:505, 张去 free(p); //释放内存不能忘记return0; }
由上例可以看出,结构体使用指针作参数时是按地址传送的,不使用指针便按值传送,说明一点,结构体是基本类型的一种扩充,符合基本类型的规律。
当结构体中的元素的取值范围很小时,可以将几个字段按位合成一个字段来表示,起到节省内存空间的作用。
![]()
#include<stdio.h>#include<string.h>structb_type {unsigned chardepart: 3 ; //部门(最大7个部门)unsigned charsex: 1 ; //性别unsigned charreason: 2 ; //理由(共4个) };voidprint(structb_type *rea) {chardep[7];charsex[3];charres[5];switch(rea->depart) {case1: strcpy(dep,"财务科"); break;case2: strcpy(dep,"开发科"); break;case3: strcpy(dep,"检测科"); break;case4: strcpy(dep,"生产科"); break;:defaultbreak; } switch (rea->sex) {case0: strcpy(sex,"男"); break;default: strcpy(sex,"女"); break; } switch (rea->reason) {case1: strcpy(res,"事假");break;case2: strcpy(res,"病假");break;case3: strcpy(res,"婚假");break;default: strcpy(res,"无故");break; } printf("%s, %s, %s\n", dep, sex, res);return; }intmain(void) {structb_type staff; staff.depart = 2; staff.sex = 0; staff.reason =4; printf("staff的长度:%d\n",sizeof(structb_type)); print(&staff);return0; }
C语言同样允许没有标记名的结构体。
![]()
#include<stdio.h>#include<string.h>intmain(void) {struct{charid[4] ; //编码charname[16] ; //姓名 } staff, *p; strcpy(staff.id, "101"); strcpy(staff.name, "后羿"); p = &staff ; printf("%s, %s\n", p->id, p->name);return0; }