一、内存管理
32为系统最多容纳4g内存
地址总线是32位,就是寻址空间是32位
32位值的是给内存编号只能编到32个二进制位
2根总线能表示4个状态(00、01、10、11),所以32位总线就是2的32次方可以存储2的32次方个字节
操作系统会使用管理的内存一部分,用户基本是64位的48位的比例
内存管理图
编译好的代码放到磁盘,使用的时候加载到代码段
全局变量和局部变量、常量放到数据段
栈存储执行记录细节,最先分配的栈地址编号大一些
变量的本质=代号=内存
指针的本质=内存地址-à找到变量存储的值所在地址
二、c语言的预处理和宏定义
gcc –o hello.i hello.c –E编译生成.i文件
预处理:点i文件是#include <stdio.h>头文件的展开,将stdio.h的代码写入.c预处理成.i,然后进行.s编译
宏定义:预处理过程发生替换值过程
预处理下的宏定义:常量、数组可以声明成宏
宏函数使用
Typedef:给变量取别名属于c语句,宏不属于c
使用方式:typedef int tni;
三、结构体的使用
#include <stdio.h>
//声明一个结构体
struct wea{
char name[20];
int atk;
int price;
};
int main(){
int a=0;
float b=0.0;
//使用结构体并且初始化
struct wea wea_01={"机关枪",1,2000};
printf("%s\n,%d\n",wea_01.name,++wea_01.price);
struct wea wea_02[2] = {{"M4A1",50,1000},{"RPK",10,2300}};
printf("%s\n,%d\n",wea_02[0].name,wea_02[0].atk);
return 0;
}
最宽的是否是当前结构体大小整数倍,是则ok,以最后变量字节整除计算4/12能够整除,最后变量作填充,当不能整除情况。
查看结构体占用空间大小
四、结构体指针
#include <stdio.h>
//声明一个结构体
struct wea{
char name[20];
int atk;
int price;
};
int main(){
int a=0;
float b=0.0;
//使用结构体并且初始化
struct wea wea_01={"机关枪",1,2000};
printf("%s\n,%d\n",wea_01.name,++wea_01.price);
//声明指针结构体引用
struct wea * w;
//赋值
w=&wea_01;
//获取wea_01里的值
printf("name=%s\n,name=%s\n",(*w).name,w->name);// w->name 指向运算符
struct wea wea_02[2] = {{"M4A1",50,1000},{"RPK",10,2300}};
printf("%s\n,%d\n",wea_02[0].name,wea_02[1].atk);
struct wea * p;
p=wea_02;//p->name wea_02[0].name
printf("%d\n",p->atk);
p++; //wea_02 +1=wea_02[1];
return 0;
}
五、公用体(让几个不同的变量共享同一个内存地址)
#include <stdio.h>
union data{ //根据成员最长字节定义自己长度
int a;
char b;
int c;
};
int main(){
union data data_01;//只能有一个常量
data_01.a='C';
data_01.b=22;//会覆盖上面的值
printf("%p\n,%p\n,%p\n",data_01.a,data_01.b,data_01.c);
return 0;
}
六、动态数据结构(连续的内存空间ab->bc->ca)
静态数据结构不能灵活利用内存空间大小。
静态链表的使用
#include <stdio.h>
struct weapon{
int price;
int atk;
struct weapon * next;//使用指针,便于指向下一个内存空间
};
int main(){
struct weapon a,b,c, *head;//头指针
a.price=100;
a.atk=60000;
b.price=120;
b.atk=70000;
c.price=80;
c.atk=100;
//首尾连接成链表结构
head=&a;
a.next=&b;
b.next=&c;
c.next=NULL;
//借助指针访问节点
struct weapon *p;
p=head;
while(p!=NULL){
printf("%d\n,%d\n",p->price,p->atk);
p=p->next;//当c为null终止循环
}
return 0;
}
动态链表
#include <stdio.h>
#include <malloc.h>
struct weapon{
int price;
int atk;
struct weapon * next;//使用指针,便于指向下一个内存空间
};
//定义创建动态链表结构函数
struct weapon * create(){
struct weapon *head;
struct weapon *p1,*p2;
//记录当前链表节点个数
int n=0;
//malloc是分配内存块的函数,sizeof判断内存长度符
p1=p2=(struct weapon*)malloc(sizeof(struct weapon));
//输入节点数据
scanf("%d\n,%d\n",&p1->price,&p1->atk);
//开始链表不存在,先给head空值
head=NULL;
//开始处理大量输入的数据
//约定什么时候输入结束,录入有限个数数据,当为0不连接链表,不为0才让连入链表
while(p1->price!=0){
n++;
//第一个添加到链表的节点就赋值给head,生成头指针
if(n==1) head=p1;
else p2->next=p1;//不是第一次就用上一个节点指向当前节点p1
//第一次添加节点完成后保留p1节点地址给p2
p2=p1;
//开辟一个新的动态存储区,再给p1
p1=((struct weapon*)malloc(sizeof(struct weapon)));
scanf("%d\n,%d\n",&p1->price,&p1->atk);
}
p2->next=NULL; //结束清除内存
return (head);
}
int main(){
struct weapon *p;
p=create();
printf("%d\n,%d\n",p->price,p->atk);
return 0;
}
七、c位运算符
按位与
按位或:设定数据指定位
按位异或:定位反转
左移运算:左移若干位,高位丢弃,低位补零
函数递归调用
返回的时候把值和参数压入栈里面,再返回值的地址给主调函数,函数没调用一次复制一个副本由栈管理(该副本有独立的内存单元)