------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、结构体
1.概念:结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,叫做结构。
2.作用:结构体和其他类型基础数据类型一样,例如int类型,char类型 只不过结构体可以做成你想要的数据类型。以方便日后的使用。
3.在函数中的作用:结构体在函数中的作用就是封装。封装的好处就是可以再次利用。让使用者不必关心这个是什么,只要根据定义使用就可以了。
4.实际开发中,多种类型的数据组合在一起来表示一种新的数据,这个需求非常多。如表示一个学生的信息有 : 姓名 ,年龄 ,身高 ,体重等。
#include <iostream>
typedef struct {
char *name;
int age;
double height;
int weight;
} Student;
/*
如果不用typedef应该这样写
声明 :
struct Student{
char *name;
int age;
double height;
int weight;
};
定义 :
struct Student s = {"Mike" ,22 ,175.5 ,50};
或者 :
struct {
char *name;
int age;
double height;
int weight;
} stu;
stu.name = "Mike";
stu.age = 22;
stu.height = 175.5;
stu.weight = 50;
*/
int main(){
Student s = {"Mike" ,22 ,175.5 ,50};
printf("name : %s" ,s.name);
printf("age : %d" ,s.age);
printf("height : %f" ,s.height);
printf("weight : %d" ,s.weight);
return 0;
}
5.内存分析:
对齐算法:结构体所占用内存空间的大小,一定是结构体中
最大成员所占用存储空间的倍数
。
例如:
struct Student
{
int age; // 4个字节
char *name; // 8个字节
}stu;
结构体所占用的字节:16个字节(8的倍数)。内存分配:定义结构体类型时不会分配内存空间,只有当赋值的时候才能分配存储空间。
6.
结构体类型不能够重复定义
定义结构体变量的三种方式:(从类型和变量进行考虑)
a.先定义类型(相当于int、double等),再定义变量
struct student
{
int age;
};
struct student stu;
b.
定义类型的同时定义变量
struct student
{
int age;
} stu;
c.
定义类型的同时定义变量,但是省略类型名称
struct
{
int age;
} stu;
7.
作用域
a.定义在函数内部:从定义那一行开始,到函数或代码块结束。(跟局部变量一样)
b.定义在函数外部:从定义那一行开始,到程序结尾。(跟全局变量一样)
8.
结构体数组(结构体中定义结构体):
struct student stu[3] = { { },{ },{ } } // 结构体数组中含有三个结构体
数组修改方式:错误修改:stu[0]={ };正确修改:stu[0].age=10;
9.
指向结构体的指针
struct student *p;
p=&stu;
有三种方法访问结构体属性:
a:stu.age;
b:(*p).age;//代表指针访问结构体中的age属性
c:p->age;//代表指针访问结构体中的age属性 (最常用)
10.结构体使用注意:
a.结构体不能递归定义
b.结构体内可以包含其他结构体
struct Date{
int year;
int month;
int day;
};
struct Student {
char *name;
struct Date birthday;
};
c.
结构体只有在定义的时候才会分配存储空间,分配存储空间的原则符合对其算法
/*
对于结构体的对齐算法 :
在定义变量的时候会依据结构体占用内存最大的成员为单位为结构体变量分配存储空间
*/
#include <stdio.h>
// 声明结构体,不会分配存储空间
typedef struct {
char *name; // 64位编译器 : 占用内存8byte
int age; // 4byte
} Student;
int main (){
Student s = {"Mike" ,22}; //定义结构体变量会分配存储空间
printf("size is : %ld\n",sizeof s); // size is : 8 ,符合对齐算法
return 0;
}
d.
结构体初始化问题
#include <stdio.h>
typedef struct {
char *name; // 64位编译器 : 占用内存8byte
int age; // 4byte
} Student;
int main(){
Student s = {"Mike" ,22}; // 对于这种初始化方式{..}只适用声明变量的时候
// s = {"Mike" ,22}; // 错误写法
return 0;
}
e.
结构体指针适用注意
/*
结构体指针变量的定义形式:struct 结构体名称 *指针变量名
有了指向结构体的指针,那么就有3种访问结构体成员的方式
结构体变量名.成员名
(*指针变量名).成员名
指针变量名->成员名
*/
#include <stdio.h>
typedef struct {
char *name; // 64位编译器 : 占用内存8byte
int age; // 4byte
} Student;
int main(){
Student *s;
Student s1 = {"Mike" ,22};
s = &s1;
printf("name is : %s ,age is : %d\n",s->name,s->age); // name is : Mike ,age is : 22
printf("name is : %s ,age is : %d\n",(*s).name,(*s).age); // name is : Mike ,age is : 22
system("pause");
return 0;
}
二、枚举
1.枚举是C语言中的一种基本数据类型,并不是构造类型,它可以用于声明一组常数。当一个变量有几个固定的可能取值时,可以将这个变量定义为枚举类型。比如,你可以用一个枚举类型的变量来表示季节,因为季节只有4种可能的取值:春天、夏天、秋天、冬天。
2.关键词:enum 其余定义方法和结构体一样
1.定义:a.预处理指令是在程序开始编译前就已经编译完毕了。b.全部是#开头。
3.作用:固定变量的取值范围。(
枚举类型中定义的变量只能取枚举中的属性。)
// 一般形式为:enum 枚举名 {枚举元素1,枚举元素2,……};
// 下面方式均等价
// (1)
// 定义枚举类型
enum WeedDay {Monday,Tuesday,Wednesday,Thursday,Friday,Saturary,Sunday};
// 定义枚举变量
enum WeedDay day;
// (2)
enum WeedDay {Monday,Tuesday,Wednesday,Thursday,Friday,Saturary,Sunday} day;
// (3)
enum {Monday,Tuesday,Wednesday,Thursday,Friday,Saturary,Sunday} day;
三、预处理指令
1.定义:a.预处理指令是在程序开始编译前就已经编译完毕了。b.全部是#开头。
分类: 宏定义、条件编译、文件包含
作用域:从编写指令开始,一直到文件结尾。
2.
宏定义:宏定义作用简单来说就是文本替换。宏名的书写习惯一般都是大写以便跟变量区分开。
a.
不带参数的宏定义: #define 宏名 字符串
#define PI 3.14
// 计算圆的周长
int main (){
int r = 2;
float rith = 2 * PI * r; // 在编译之前PI会替换为3.14
printf("半径为 : %d 的圆周长为 : %f",r ,rith);
return 0;
}
b.
带参数的宏 : #define 宏名 ( 参数列表 ) 字符串
一般写法:#define 宏名 (参数1,参数2) ( (参数1)..(参数2) )
#define SUM ( a , b ) ( ( a ) + ( b ) )
int main () {
int sum = SUM( 1 , 1 ) * 2;
printf("( 1 + 1 ) * 2 = %d",sum);
return 0;
}
c.
取消宏定义:#undef 宏名
#define PI 3.14;
int main(){
// 正确写法
float pi = PI;
#undef PI
// 宏定义在上一行已经失效了,因此以下代码不能在使用该宏名
// float pi1 = PI;
return 0;
}
3.条件编译
#if()
A //如果只编译了A,则下面的B和C不会保存在内存中
#elif()
B
#else()
C
#endif
注:a.条件编译只编译宏中定义的语句,且如果elif或else没有判断,则此没有保存在内存中(不参与编译的不会保存在内存中)。
b.endif必须添加
c.#if defined() 相当于 #ifdef
d.#if undefined 相当于#ifndef
例子:
#define A = 5;
int main (){
#if A > 5
printf("A > 5");
#elif A == 10
printf("A == 5"); // 程序运行结果
#else
printf("A < 5");
#endif
return 0;
}
4.
文件包含 #include
a.简介:文件包含使用频率比较高,它可以将一个文件的全部内容拷贝到另外一个文件中
b.#include <文件名>:直接根据文件名到C语言函数库偷文件所在的目录寻找
c.#include "文件名":
系统会先在当前目录下寻找如果找不到,在到系统的path路径中查找,最后才到C语言函数头文件所在目录查找
d.重复包含问题:文件包含的作用简单来说是存文本复制,但很容易会发生重复包含问题 :
四、总结与心得
1.结构体和其他类型基础数据类型一样。
2.枚举可以创建一组代表整数常量的符号(枚举常量),也允许定义相关联的枚举类型。
3.C的预处理器是C的重要附件。执行预处理指令可以在编译代码前对源代码进行调整。
#define PI 3.14
// 计算圆的周长
int main (){
int r = 2;
float rith = 2 * PI * r; // 在编译之前PI会替换为3.14
printf("半径为 : %d 的圆周长为 : %f",r ,rith);
return 0;
}
b.
带参数的宏 : #define 宏名 ( 参数列表 ) 字符串
#define SUM ( a , b ) ( ( a ) + ( b ) )
int main () {
int sum = SUM( 1 , 1 ) * 2;
printf("( 1 + 1 ) * 2 = %d",sum);
return 0;
}
c.
取消宏定义:#undef 宏名
#define PI 3.14;
int main(){
// 正确写法
float pi = PI;
#undef PI
// 宏定义在上一行已经失效了,因此以下代码不能在使用该宏名
// float pi1 = PI;
return 0;
}
3.条件编译
#if()
A //如果只编译了A,则下面的B和C不会保存在内存中
#elif()
B
#else()
C
#endif
注:a.条件编译只编译宏中定义的语句,且如果elif或else没有判断,则此没有保存在内存中(不参与编译的不会保存在内存中)。
b.endif必须添加
c.#if defined() 相当于 #ifdef
d.#if undefined 相当于#ifndef
例子:
#define A = 5;
int main (){
#if A > 5
printf("A > 5");
#elif A == 10
printf("A == 5"); // 程序运行结果
#else
printf("A < 5");
#endif
return 0;
}
4.
文件包含 #include
d.重复包含问题:文件包含的作用简单来说是存文本复制,但很容易会发生重复包含问题 :
四、总结与心得
1.结构体和其他类型基础数据类型一样。
2.枚举可以创建一组代表整数常量的符号(枚举常量),也允许定义相关联的枚举类型。
3.C的预处理器是C的重要附件。执行预处理指令可以在编译代码前对源代码进行调整。