目录
前言:什么是结构体
1.结构体的声明
2. 结构体变量的定义和初始化
2.1结构体变量的定义
2.2结构体变量的初始化
2.3结构体嵌套及初始化
3. 结构体成员的访问
3.1可通过“ . ”操作符访问
3.2 指向结构体变量的指针访问
4. 结构体传参
前言:什么是结构体
在解决实际问题中除了已有的整形(int,long等)、浮点型(flaot,double)、字符型(char)、数组等数据类型是不够的。比如我们统计一本书的信息,就需要保存它的书名(char),作者(char),价格(double),出版时间(int)等等,这些数据类型不相同但又是一个整体,我们就需要定义一个新的数据类型——结构体。利用结构体把这些数据保存起来。
结构体是由一批数据组合而成的结构型数据。组成结构型数据的每个数据称为结构型数据的“成员” ,其描述了一块内存区间的大小及解释意义。结构体是C语言中一种重要的数据类型,该数据类型由一组称为成员(或称为域,或称为元素)的不同数据组成,其中每个成员可以具有不同的类型。结构体通常用来表示类型不同但是又相关的若干数据。
1.结构体的声明
//声明一个结构体的标准格式
struct 名称 //这里的名称在c语言中可以省略,但不推荐。
{
成员变量1;
········· //成员变量在c语言中不可省略,只是要有1个成员
成员变量n;
};
//例:
struct book
{
char name[10]; //表示书名的字符串
double price; //表示书价格的数
int time; //表示书的出版时间
};
struct 表示接下来的是一个结构体。
声明结构体的本质:声明结构体的本质就是新增一种数据类型。
在解决实际问题中除了已有的整形(int,long等)、浮点型(flaot,double)、字符型(char)、数组等数据类型是不够的。比如我们统计一本书的信息,就需要保存它的书名(char),作者(char),价格(double),出版时间(int)等等,这些数据类型不相同但又是一个整体,我们就需要定义一个新的数据类型——结构体。利用结构体把这些数据保存起来。
结构体是由一批数据组合而成的结构型数据。组成结构型数据的每个数据称为结构型数据的“成员” ,其描述了一块内存区间的大小及解释意义。结构体是C语言中一种重要的数据类型,该数据类型由一组称为成员(或称为域,或称为元素)的不同数据组成,其中每个成员可以具有不同的类型。结构体通常用来表示类型不同但是又相关的若干数据。
//声明一个结构体的标准格式 struct 名称 //这里的名称在c语言中可以省略,但不推荐。 { 成员变量1; ········· //成员变量在c语言中不可省略,只是要有1个成员 成员变量n; }; //例: struct book { char name[10]; //表示书名的字符串 double price; //表示书价格的数 int time; //表示书的出版时间 };struct 表示接下来的是一个结构体。
声明结构体的本质:声明结构体的本质就是新增一种数据类型。
2. 结构体变量的定义和初始化
2.1结构体变量的定义
1.假如我们声明过了结构体类型,那么就可以直接定义结构体变量b1。例如:
struct book b1;
//格式:struct 名称 变量名
2.每次定义结构体变量时,都得 struct 名称 变量名;不方便。这里我们就用到了 typedef(类型重命名),可以用typedef为已有的数据类型取一个新的名字,可以使程序书写简单,增强程序的可读性。
//方法一:
typedef struct 名称1
{
成员变量1;
·········
成员变量n;
}名称2;
//方法二:
struct 名称1
{
成员变量1;
·········
成员变量n;
}
typedef struct 名称1 名称2;
在结构体变量的定义时,我们可以不再用 “ struct 名称1 变量名;” 这样的的方法来定义,可以直接“名称2 变量名;”来定义它。
例:
typedef struct book
{
char name[10];
double price;
int time;
}shu;
在结构体变量的定义时,我们可以不用 struct book b2;的方法来定义,可以直接 shu b2;来定义b2.
1.假如我们声明过了结构体类型,那么就可以直接定义结构体变量b1。例如:
struct book b1; //格式:struct 名称 变量名2.每次定义结构体变量时,都得 struct 名称 变量名;不方便。这里我们就用到了 typedef(类型重命名),可以用typedef为已有的数据类型取一个新的名字,可以使程序书写简单,增强程序的可读性。
//方法一: typedef struct 名称1 { 成员变量1; ········· 成员变量n; }名称2; //方法二: struct 名称1 { 成员变量1; ········· 成员变量n; } typedef struct 名称1 名称2;在结构体变量的定义时,我们可以不再用 “ struct 名称1 变量名;” 这样的的方法来定义,可以直接“名称2 变量名;”来定义它。
例:
typedef struct book { char name[10]; double price; int time; }shu;在结构体变量的定义时,我们可以不用 struct book b2;的方法来定义,可以直接 shu b2;来定义b2.
2.2结构体变量的初始化
定义结构体变量的同时可以被整体赋初始值。
例:
//方法1.
struct book
{
char name[10];
double price;
int time;
}b3 = { "白夜行",49.80,1999 };
//方法2.
struct book
{
char name[10];
double price;
int time;
}
struct book b3 = { "白夜行",49.80,1999 };
结构体类似于数组,只可被整体初始化,不可被整体赋值!
不可以:
struct book
{
char name[10];
double price;
int time;
}b3;
struct book b3 = { "白夜行",49.80,1999 };//不可以在声明之后这样赋值
或者
book b3 = { "白夜行",49.80,1999 };//不可以在声明之后这样赋值
或者
b3 = { "白夜行",49.80,1999 };//不可以在声明之后这样赋值
这样编译器会报错!
2.3结构体嵌套及初始化
现在我们要在刚才所声明的结构体:
struct book
{
char name[10]; //表示书名的字符串
double price; //表示书价格的数
int time; //表示书的出版时间
};
内部再嵌套一个结构体:
struct position
{
double x; //表示书在书架的几排
double y; //表示书在书架的几列
};
嵌套后:
struct book
{
char name[10]; //表示书名的字符串
double price; //表示书价格的数
int time; //表示书的出版时间
struct position b4;//表示书的位置
};
那么此时我们如何初始化结构体变量b3呢?和二维数组的初始化相似:
struct book b3={"白夜行",49.80,1999,{3,2}};
3. 结构体成员的访问
3.1可通过“ . ”操作符访问
其一 般形式为:结构体变量名.成员变量。
结构体中的成员变量用法和普通变量是一样的。
比如:可以给成员变量单独赋值(不可以被整体赋值!!!)
例子:
3.2 指向结构体变量的指针访问
struct book b3 = { "白夜行",49.80,1999 };
struct *p=&b3;
结构体变量的指针引用结构体变量的成员分量
方法一 :使用 * 运算符
printf("%dn", (*p).time);
方法二 :使用 -> 指向运算符
printf("%dn", p->time);
4. 结构体传参
#include
struct book
{
char name[10];
double price;
int time;
};
struct book b3 = { "白夜行", 49.80, 1999};
void ShowBook1(struct book n)
{
printf("%sn", n.name);
printf("%lfn", n.price);
printf("%dn", n.time);
}
void ShowBook2(struct book *p)
{
printf("%sn", p->name);
printf("%lfn",p->price);
printf("%dn", p->time);
}
int main()
{
ShowBook1(b3);
ShowBook2(&b3);
return 0;
}
ShowBook1() 传的是结构体,ShowBook2() 传的是结构体的地址 。
函数传参时,会发生零时拷贝。往ShowBook1()传参时传的是结构体,所以零时拷贝的也是结构体。往ShowBook2()传参时传的是结构体的地址,所以零时拷贝的也是结构体的地址。
若结构体所占的内存较大,往ShowBook1()传参时,临时拷贝的数据也会非常大,调用函数的成本会非常高。所以推荐使用ShowBook2() 函数,只需要拷贝结构体的地址,不管结构体有多大,都会非常稳定。总的来说:结构体传参的时候,要传结构体的地址。
定义结构体变量的同时可以被整体赋初始值。
例:
//方法1.
struct book
{
char name[10];
double price;
int time;
}b3 = { "白夜行",49.80,1999 };
//方法2.
struct book
{
char name[10];
double price;
int time;
}
struct book b3 = { "白夜行",49.80,1999 };
结构体类似于数组,只可被整体初始化,不可被整体赋值!
不可以:
struct book
{
char name[10];
double price;
int time;
}b3;
struct book b3 = { "白夜行",49.80,1999 };//不可以在声明之后这样赋值
或者
book b3 = { "白夜行",49.80,1999 };//不可以在声明之后这样赋值
或者
b3 = { "白夜行",49.80,1999 };//不可以在声明之后这样赋值
这样编译器会报错!
现在我们要在刚才所声明的结构体:
struct book { char name[10]; //表示书名的字符串 double price; //表示书价格的数 int time; //表示书的出版时间 };内部再嵌套一个结构体:
struct position { double x; //表示书在书架的几排 double y; //表示书在书架的几列 };嵌套后:
struct book { char name[10]; //表示书名的字符串 double price; //表示书价格的数 int time; //表示书的出版时间 struct position b4;//表示书的位置 };那么此时我们如何初始化结构体变量b3呢?和二维数组的初始化相似:
struct book b3={"白夜行",49.80,1999,{3,2}};
3. 结构体成员的访问
3.1可通过“ . ”操作符访问
其一 般形式为:结构体变量名.成员变量。
结构体中的成员变量用法和普通变量是一样的。
比如:可以给成员变量单独赋值(不可以被整体赋值!!!)
例子:
3.2 指向结构体变量的指针访问
struct book b3 = { "白夜行",49.80,1999 };
struct *p=&b3;
结构体变量的指针引用结构体变量的成员分量
方法一 :使用 * 运算符
printf("%dn", (*p).time);
方法二 :使用 -> 指向运算符
printf("%dn", p->time);
4. 结构体传参
#include
struct book
{
char name[10];
double price;
int time;
};
struct book b3 = { "白夜行", 49.80, 1999};
void ShowBook1(struct book n)
{
printf("%sn", n.name);
printf("%lfn", n.price);
printf("%dn", n.time);
}
void ShowBook2(struct book *p)
{
printf("%sn", p->name);
printf("%lfn",p->price);
printf("%dn", p->time);
}
int main()
{
ShowBook1(b3);
ShowBook2(&b3);
return 0;
}
ShowBook1() 传的是结构体,ShowBook2() 传的是结构体的地址 。
函数传参时,会发生零时拷贝。往ShowBook1()传参时传的是结构体,所以零时拷贝的也是结构体。往ShowBook2()传参时传的是结构体的地址,所以零时拷贝的也是结构体的地址。
若结构体所占的内存较大,往ShowBook1()传参时,临时拷贝的数据也会非常大,调用函数的成本会非常高。所以推荐使用ShowBook2() 函数,只需要拷贝结构体的地址,不管结构体有多大,都会非常稳定。总的来说:结构体传参的时候,要传结构体的地址。
其一 般形式为:结构体变量名.成员变量。
结构体中的成员变量用法和普通变量是一样的。
比如:可以给成员变量单独赋值(不可以被整体赋值!!!)
例子:
3.2 指向结构体变量的指针访问
struct book b3 = { "白夜行",49.80,1999 };
struct *p=&b3;
结构体变量的指针引用结构体变量的成员分量
方法一 :使用 * 运算符
printf("%dn", (*p).time);
方法二 :使用 -> 指向运算符
printf("%dn", p->time);
4. 结构体传参
#include
struct book
{
char name[10];
double price;
int time;
};
struct book b3 = { "白夜行", 49.80, 1999};
void ShowBook1(struct book n)
{
printf("%sn", n.name);
printf("%lfn", n.price);
printf("%dn", n.time);
}
void ShowBook2(struct book *p)
{
printf("%sn", p->name);
printf("%lfn",p->price);
printf("%dn", p->time);
}
int main()
{
ShowBook1(b3);
ShowBook2(&b3);
return 0;
}
ShowBook1() 传的是结构体,ShowBook2() 传的是结构体的地址 。
函数传参时,会发生零时拷贝。往ShowBook1()传参时传的是结构体,所以零时拷贝的也是结构体。往ShowBook2()传参时传的是结构体的地址,所以零时拷贝的也是结构体的地址。
若结构体所占的内存较大,往ShowBook1()传参时,临时拷贝的数据也会非常大,调用函数的成本会非常高。所以推荐使用ShowBook2() 函数,只需要拷贝结构体的地址,不管结构体有多大,都会非常稳定。总的来说:结构体传参的时候,要传结构体的地址。
struct book b3 = { "白夜行",49.80,1999 };
struct *p=&b3;
结构体变量的指针引用结构体变量的成员分量
方法一 :使用 * 运算符
printf("%dn", (*p).time);
方法二 :使用 -> 指向运算符
printf("%dn", p->time);
#includestruct book { char name[10]; double price; int time; }; struct book b3 = { "白夜行", 49.80, 1999}; void ShowBook1(struct book n) { printf("%sn", n.name); printf("%lfn", n.price); printf("%dn", n.time); } void ShowBook2(struct book *p) { printf("%sn", p->name); printf("%lfn",p->price); printf("%dn", p->time); } int main() { ShowBook1(b3); ShowBook2(&b3); return 0; } ShowBook1() 传的是结构体,ShowBook2() 传的是结构体的地址 。
函数传参时,会发生零时拷贝。往ShowBook1()传参时传的是结构体,所以零时拷贝的也是结构体。往ShowBook2()传参时传的是结构体的地址,所以零时拷贝的也是结构体的地址。 若结构体所占的内存较大,往ShowBook1()传参时,临时拷贝的数据也会非常大,调用函数的成本会非常高。所以推荐使用ShowBook2() 函数,只需要拷贝结构体的地址,不管结构体有多大,都会非常稳定。总的来说:结构体传参的时候,要传结构体的地址。



