1.动态内存分配
为什么要动态申请内存?
有些函数在调用时需要传递参数,比如数组的地址,如果我们在函数里只用静态申请数组的话会使程序的可移植性降低,为了灵活使用函数,所以会用到动态申请。
使用动态申请前,需要先开空间再使用。
动态内存申请的空间在 堆区 ,堆区空间人为申请,人为释放。
调用前需用引用库函数:<stdlib.h>
申请空间:malloc
释放空间:free
函数申明:void *malloc(size_t size);
函数功能:申请size个字节大小的空间,返回空间的首地址。
申请2个int型的空间大小,对空间进行写数据,然后读数据
#include<stdio.h>
#include<stdlib.h>
void *malloc( size_t size );
void free( void *ptr );
int main(void)
{
int *p = (int *)malloc(sizeof(int)*2);
*p = 100;
*(p+1) = 200;
printf("%d %d\n",*p,*(p+1));
free(p);
//p = NULL;
printf("%d %d",*p,*(p+1));
return 0;
}
如果p=NULL省略,可以明细观察到下面不清零的情况
p=NULL不省略会出现以下情况
2.宏定义
定义一个标识符代表、常量数字、变量、表达式来使用。
#define+宏名+代表内容
“#”代表预处理符号 预处理阶段进行替换
>>宏定义的好处:方便代码的维护,一改全改;
#include<stdio.h>
预处理阶段进行 宏替换常量 变量以及表达式
#define bookNum 2000
#define NUM
#define ADD c+d
带参宏
#define 宏名(参数列表,不写类型) 表达式
#define GETHE(x,y) x + y
宏定义后面表达式的时候,为了避免运算符优先级,最好加括号()
#define SUB(x,y) (x-y)
使用宏明代表类型
给类型起别名 u8 u16 u32 unsigned char
#define u8 unsigned char
使用宏名写一个表达式求两个数中的最小值
#define Min(x,y) (x < y ? x : y)0
预处理:
#include 拷贝
#define 宏替换
#if #else 条件编译
编译: 检查语法错误
汇编: 生成二进制代码
链接: 链接静态动态库 根据不同的平台+不同平台的启动代码
3.顺便说一下const 和 static
const 修饰变量后,变量的值不能被修——变量只读;
const 变量在定义时候就要给值,即const变量必须初始化;
int a=30;
a=50;
const int b=60;//const 变量必须初始化 或者 int const c=80;
const 和指针
char str1[30] = "hello world";
char str2[30] = "xxxxx";
str1[0] = '8'; //修改str1的第一位,把h变成8
// const在*的前面修饰的是指针指向的空间 *p
// p空间没有限定
const char *p = str1;
printf("%s\n",p);
// *p = 'o'; // 报错 *p是只读
p = str2; // p是可以读写的
printf("%s\n",p);
// const放在*之后修饰的是指针本身的空间 p
// 必须要初始化,不然后面就用不了指针,不能再改变他的指向
char *const q = str1;
printf("%s\n",q);
// q = str2; // 错误 报错 q是只读
*q = 'i'; // *q可以读写
printf("%s\n",q);
--------------------------------------------
const char *p = str1;
char *const q = str1;
const char *const p = str1;
// p和 *p都是只读的。
const char *p = str1;
char const *t = str1; // *t是只读的,t是可以读写
!!!! cosnt int *p和 int const *p有什么区别? 没区别 !!!!
static
-- 局部变量:变量只能初始化一次,位于静态数据区,函数结束空间不会被销毁
-- 全局变量:变量只能当前文件里面使用
-- 函数: 函数只能在当前文件里面使用
可以从这段代码里理解一下
#include<stdio.h>
void test(void)
{
static int a = 1;
printf("%d\n",a);
a++;
}
int main()
{
test(); // 1
// 静态数据区 -- a = 1 a++ ; a=2
test(); // 1
// static int a = 1; --- 检测到静态数据区已经开过空间了,忽略这一条指令
// 输出 2 a++ a=3
test();
// static int a = 1; --- 检测到静态数据区已经开过空间了,忽略这一条指令
// 输出 3 a++ a=4
// printf("%d",a); 报错 a 没有定义 ,不能访问,并没有改变a是静态局部变量的属性。
return 0;
}
4.还有讲一下这个extern关键字
extern int m; // 变量声明
在使用的地方对变量声明,程序运行的时候回去别的文件里面查找这个变量。
5.结构体
5.1 数据类型——自定义类型
在写结构体之前 一定要理清楚应该需要些哪些成员名字以及成员类型!
比如:
班级同学的信息:
姓名 性别 年龄 成绩
李天 男 20 94.5
张三 男 19 65
···········
类型:字符串 字符串 整型 实型
结构体是一种自定义的数据,将多个不同数据类型的数据放在一起形成一个新的数据类型。
汽车: 品牌 价格 颜色 ...
电脑: 品牌 价格 颜色 CPU memory
按照需求先创造数据类型,之后使用创建的数据类型开空间,存取数据。
5.2 定义结构体数据类型
格式:
struct 结构体名称
{
成员类型 成员名;
成员类型 成员名;
成员类型 成员名;
成员类型 成员名;
。。。。。
};
例子:
图书:图书编号 书名 作者 热度 价格
int char [40] char [30] int float
输出成这样:
结构体类型名:struct book
struct book
{
int num;
char name[40];
char author[30];
int hot;
float price;
};
5.3 typedef
以前使用数据类型 --- 数据类型关键字只有一个单词。
typedef ---- 给类型起别名。
typedef 数据类型 别名;
比如:
typedef unsigned char u8;
#define u8 unsigned char
举个例子:
typedef struct book
{
int num;
char name[40];
char author[30];
int hot;
float price;
}BK;
结构体类型名:struct book
typedef struct book BK;
BK 就是 struct book,是数据类型
5.4 结构体变量
先定义再使用
typedef struct book
{
int num;
char name[40];
char author[30];
int hot;
float price;
}BK;
struct book a;
//结构体变量通过 . 语法找到成员
//a.num --- int
//a.name --- 数组名
//a.author --- 数组名
//a.hot --- int
//a.price --- float
对应的:
a.num = 1;
strcpy(a.name,"C语言");
strcpy(a.author,"谭浩强");
a.hot = 4;
a.price = 36.5;
然后输出
printf("%d %s %s %d %.2f",a.num,a.name,a.author,a.hot,a.price);
定义类型后直接定义变量
struct book
{
int num;
char name[40];
char author[30];
int hot;
float price;
}b1,b2;
//b1.num --- int
//b1.name --- 数组名
//b1.author --- 数组名
//b1.hot --- int
//b1.price --- float
//b2.num --- int
//b2.name --- 数组名
//b2.author --- 数组名
//b2.hot --- int
//b2.price --- float
tips:
结构体定义如果前面有 typedef 后面是类型别名。
结构体定义如果前面没有typedef 后面是变量
————————————————————————————————
5.5结构体变量初始化
!!!按照成员定义的顺序赋值 不能跳跃!!!
struct book
{
int num;
char name[40];
char author[30];
int hot;
float price;
};
struct book b1 = {1,"C语言","",5,34.5};
struct book b2 = {1,"C语言","",5};
或者
struct book
{
int num;
char name[40];
char author[30];
int hot;
float price;
}b3={1,"C语言","",5,34.5};
5.6 结构体变量间可以通过 = 赋值
#include<stdio.h>
struct book
{
int num;
char name[40];
char author[30];
int hot;
float price;
}b3={1,"C语言","",5,34.5};
int main()
{
struct book b4;
b4 = b3;
printf("%d %s %s %d %.2f",b4.num,b4.name,b4.author,b4.hot,b4.price);
return 0;
}
5.7 结构体指针
最难的指针来了!
结构体类型* 指针名;
用指针找到对应地址然后输出对应值
成员访问符号 ->
p->num --- int
p->name --- 数组名
p->author --- 数组名
p->hot ---- int
p->price ---- price
#include<stdio.h>
struct book
{
int num;
char name[40];
char author[30];
int hot;
float price;
};
int main()
{
struct book b1 = {1,"C语言","",5,34.5};
struct book* p;
p = &b1;
printf("%d %s %s %d %.2f",p->num,p->name,p->author,p->hot,p->price);
return 0;
}
Last but not least:
Ending!!!
脑袋发蒙了!!
已经不想再思考了!