C语言第七节-结构体-枚举-typedef
来源:互联网 发布:上帝软件wpe1.0 编辑:程序博客网 时间:2024/06/05 06:56
fgets():是一个文件操作相关的函数,暂时使用这个函数可以从键盘接受一个字符串,保存在数组中
原型:fgets(char *p, int len, FILE)
键盘接收:fgets(str, 50,stdin) //键盘输入缓冲区
接受字符串的方法:char str[50]
1、scanf(“%s”, str) //缺点:不能接收空格,可能越界,不安全
2、gets(str) //优点:可以接受空格
//会有一个警告:当字符串长度为50时,就没有空间存结束符\0
3、fgets() //继承1,2的优点,弥补2的缺点,当长度大于50,自动在第50个位置存上\0,替换输入的第50个字符;小于50时,会保存回车符\n,然后再存上\0
fputs():也是一个文件操作相关的函数
原型:fputs(char *p , FILE)
fputs(数组名,stdout) //输出到控制台,和puts一样也不能格式化输出,但是puts可以自动换行
const:类型修饰符,使用const修饰变量则可以让变量的值不能修改
const使用的地方:
1、修饰变量:使得变量变常量,不可改
2、修饰指针变量:
1)const int *P 指向可变,指向的变量的值不可变
2) int * const p 指向不可变,指向的变量的值可变
3)const int * const p 指向不可变,指向的变量的值也不可变
记忆技巧:const和*的位置,左,右,两则
3、修饰数组
内存管理的概念和内存分区
概念:是指软件运行时对计算机内存资源的分配和使用技术。主要目的是如何高效,快速地分配,并且再适合的时候释放和回收内存资源。
内存的分配方式:
1、从静态存储区域分配
2、从栈上分配
3、从堆上分配,亦称动态内存分配
内存分区:
BSS段:未初始化的全局变量和静态变量
数据段(常量区):已初始化的全局变量和静态变量,字符串常量
代码段:程序执行代码的一块内存区域
堆(heap):动态分配的内存段
栈(stack):用户存放程序临时创建的局部变量
常见内存分配函数(堆区):
1、malloc
void*malloc (unsigned size),size是内存分配的字节,库函数stdlib.h,一般要判断是否分配成功
从内存的堆区分配大小为size个字节的连续的内存空间
如果内存分配成功 返回内存的首地址
失败 NULL
//从内存中申请一块内存空间,可以存储4个整数
int *p = (int *)malloc(4* sizeof(int)); //16个字节,void *强制转换为int *
if (p!=NULL) {
//申请成功做的事情
//申请成功做的事情
//p中存放的是新申请的内存空间的首地址
//注意:malloc申请的空间如果不赋值,则存放的是垃圾数
*p =10;
*(p + 1) =100;
*(p + 2) =1000;
*(p + 3) =10000;//存放4个整数
} else {
//内存申请失败
printf("内存申请失败!\n");
*(p + 1) =100;
*(p + 2) =1000;
*(p + 3) =10000;//存放4个整数
} else {
//内存申请失败
printf("内存申请失败!\n");
}
2、calloc
calloc(块数,长度),分配指定块数和长度的内存空间,地址也是连续的
int*p = (int*)malloc(4, sizeof(int)); //四块长度为4的内存
calloc会自动初始化,初始化为0
3、realloc
可以给已经存在的空间扩充大小
p = realloc(p,40*sizeof(int) )
//想为已经存在的4个空间的P扩充36个空间,如果4的后面有36个空的内存,则返回4的首地址;如果没有36个,则另外重新申请一个40的空间,先将4里面的内容放进去之后,再返回新空间的首地址。p则指向“新”的地址
野指针和内存泄露
野指针:1、未初始化的指针 2、指针所指向的空间已经释放,再去使用指针,该指针就是野指针
内存泄露:防止内存泄露,在指针释放之前,先释放指向的空间,使用free(释放空间的首地址)函数,释放完之后,理论上不可以访问已经释放的空间,但是还是可以访问。此时的指针就是野指针,访问的结果是一些以前的垃圾值。所以为了防止这种无理的操作,我们需要:指针初始化—>使用指针结束后—>再次赋值为NULL,以防还可以访问。free(p); p = NULL
指针函数:返回值类型是一个指针(地址)的函数
形式:类型说明符 *函数名(形参表) {
函数体
返回的是地址
}
函数指针:指向函数(函数的首地址就是函数名)的指针变量
形式:类型说明符 (*变量名)(函数的参数)
初始化:int (*p)(int a , int b) = ∑ //sum是一个求和函数
定义函数指针的时候可以不写形参名,但是类型必须写
构造类型及结构体
构造类型:根据已定义的一个或多个数据类型用构造的方法定义的。一个构造类型的值可以分解为若干元素,每个元素又可以分为基本类型或构造类型。
分类:数组,结构体类型,共用体(联合)类型
结构体structure:存储类型相同或不同的数据
定义结构体:
struct 结构名{
成员列表;
};
//定义一个学生结构体
struct student{
//学生学号
int ID;
//姓名
char name[21];
//年龄
int age;
//成绩
float score;
struct student{
//学生学号
int ID;
//姓名
char name[21];
//年龄
int age;
//成绩
float score;
};//分号不能省
结构变量成员访问:结构变量名.成员名 //stu.num
结构体变量的初始化:
1、先定义结构体变量,再初始化
struct student stu1;
//给结构体变量初始化
stu1.ID = 38;
stu1.age = 18;
stu1.ID = 38;
stu1.age = 18;
stu1.score= 59.9;
//字符串类型的初始化,如果是数组不可以写成stu1.name = "张三丰";应该用strcpy函数拷贝;如果不是数组则可以。但是定义的同时初始化则也可以
strcpy(stu1.name,"张三丰");
//UTF-8国际通用编码,一个汉字占用三个字节
2、定义的同时,进行完全初始化
struct student stu2 = {8, “凤姐”, 18, 49.99f};
3、定义的同时,指定元素初始化
struct student stu3 = {.name = “小三"};
结构体变量的存储原理:结构体占用的内存空间是每个成员占用的字节之和(考虑对齐问题)
对齐问题:
计算结构体变量在内存中占用的字节数的方法:
1、先计算对齐模数:(结构体中基本数据类型占用字节最大的那个)
2、再计算结构体变量中各个成员占用的字节和
结构体作用域:与局部变量、全局变量相似
结构数组:每一个元素都是具有相同结构类型的下标结构变量
格式: struct 结构名{ 成员列表
}数组名[数组长度];
1、定义结构体的同时,定义数组:如格式
2、先定义结构体,再定义数组:struct student a[5];
结构数组初始化:
1、ctrcpy
2、scanf
结构体指针定义和初始化
结构指针:指向结构体变量的指针
1、
2、struct Car{
int lunzi;
int speed;
}*p;
结构指针间接访问成员的值
形式:(*p).成员名 或 p->成员名 //(*p).lunzi 或 p->lunzi
结构体嵌套:成员可以使基本数据类型,又可以是一个结构
结构体可以嵌套其他结构的变量,不可以嵌套自己的变量,但是可以嵌套自己的指针
嵌套的结构体初始化
struct Student stuff = {“张丹峰”, 12,33,399f,{1991,9,3}};
结构体变量名及成员,结构体指针作为函数参数
1、成员值做函数的参数:本质上就是一个值传递
2、结构体变量名作为函数的参数:也是值传递(不能修改)
3、结构体指针作为函数的参数:地址传递
枚举
枚举:变量的取值被限定在一个有限的范围内,是一种基本数据类型,不是构造类型
形式:enum 枚举类型名{枚举值表};
在枚举值表中应罗列所有的可用值,这些值也称为枚举元素
系统默认会为枚举元素赋初值,依次从0开始,下一个为上一个加1
手动赋值:可以随便赋值k,但是下一个枚举元素的值为k+1
枚举类型变量:enum 枚举类型名 变量名;
typedef
typedef:为数据类型取别名
形式:typedef 原类型名 新类型名
使用:1、基本数据类型
typedef int MLXG;
MLXGqiezi = 3;
2、用在数组:
typedef int array[5];
arraya1; //a1就是一个长度为5数组
3、给结构体
1) struct Person{
char *name;
int age;
};
typedef struct Person p;
int age;
};
typedef struct Person p;
p p1 = {"xxx",28};
2)typedef struct Car{
int lunzi;
int speed;
}MYCAR;
int lunzi;
int speed;
}MYCAR;
MYCAR car1 = {1,200};//此中的Car可以没有,便是给匿名的结构体取个别名
4、给枚举类型
和结构体类似,也存在匿名的取别名
5、给函数指针:指向函数的指针
int sum(int a, int b) {
return a + b;
}
int (*p)(int,int);
//FUN是一个别名
//FUN是一个别名
typedef int (*FUN)(int,int);
FUNf1;
f1 =sum;
printf("%d\n", f1(23,34));
预处理
预处理指令:以#开头的预处理命令,包括#include ,#define
预处理:在编译之前做的一些处理(宏定义,文件包含,条件编译)
宏:特殊的标识符,标识符习惯大写。字符串替换(仅仅是替换,并不会自动加括号之类的)的过程叫做宏展开或宏替换
无参宏:#define 标识符 字符串
注意:1、#undef 取消宏
2、在字符串中出的宏不会被替换
3、宏可以嵌套定义
4、宏可以起别名
5、宏不是一个语句,不需要叫分号
有参宏:#define 宏名(形参表) 字符串
注意:1、宏的参数之间可以出现空格,但是宏名和形参之间不可以出现空格
2、在带参宏中,形参不分配内存空间
3、传值时,不要想当然的去代换,要简单的去替换之后,再计算。所以宏的参数最好用括号括起来
4、可以用宏来定义多个语句
宏定义和typedef的区别:一个仅仅是替换,一个是别名(在指针时,区别最大)
条件编译:1、按照不同的条件编译不同的程序,产生不同的目标代码,有利于程序的移植和调试
2、条件编译只编译其中满足要求的程序,目标程序较短
1、#if -#else条件编译指令
#if
#elif
.
.
#elif
#else
#endif
2、#ifdef 用来判断某个宏是否定义 如果定义了,然后执行什么
#ifndef 用来判断某个宏 如果没有定义,然后执行什么
使用条件编译指令调试BUG
0 0
- C语言第七节-结构体-枚举-typedef
- 【C语言连载六】--------变量、修饰词、结构体、枚举、typedef
- C语言(结构体、枚举、typedef)笔记 by STP
- C语言结构体,联合体,枚举与typedef
- typedef/结构体/枚举/
- 结构体 枚举 typedef
- C语言基础之结构体、共用体、枚举、类型定义typedef
- 学ios需要了解的C语言基础知识-8-结构体、枚举、typedef啥的
- C语言回顾之结构体、枚举、宏定义、typedef、extern和static的使用
- 黑马程序员--c语言:结构体、枚举、预处理指令、typedef、static与extern、递归思想
- c语言中的 结构体 枚举 以及typedef的使用(小结)
- 黑马程序员————C语言——结构体、枚举、typedef
- 黑马程序员——c语言复杂数据类型:结构体和枚举,typedef的使用
- 黑马程序员------C语言基础 结构体、枚举及关键字 typedef
- 黑马程序员---C语言基础---结构体、枚举、typedef、宏、static和extern
- C语言结构、共用体、Typedef
- C语言 数组 结构体 typedef
- C语言中typedef 与结构体
- 在Javascript定义对象
- [HDU 5489]Removed Interval[LIS]
- UI课程17 图片异步下载、KVO
- 加载xib到视图上
- 计算机网络读书笔记(谢希仁 第六版 思维导图)
- C语言第七节-结构体-枚举-typedef
- 如何在mac os中安装gdb及为gdb进行代码签名
- OCP-V31-041
- Oracle起步---创建临时表空间/表空间/创建用户/授权
- java发展史&solr配置
- Tired
- hdoj1700Points on Cycle【坐标旋转裸题】
- OCP-V13-042
- C++按格式接收输入字符(京东,滴滴,360笔试必用)