//int a[3][4] = { { 66, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } };
//读取二维数组任意元素hint int(*)a[4] i,j
//函数对于数组没有副本,数组多了会非常浪费cpu和内存
//对于一维数组,作为参数可以使用指向变量的指针
//对于二维数组可以用数组指针int(*)[4]
//由于没有副本,函数对参数的操作实际上就是对数组本身的修改
//逆序,冒泡算法中指针的应用(算法分析可参照数组一个章节)
//输出学生成绩,每个学生有4门课成绩,求平均成绩, 提取不及格
//=====================函数指针=====================
//定义函数后。编译系统编译时会为函数划定一片内存空间,这片内存空间的首地址即为函数的起始边界,也就是函数指针,函数名实际上就是个内存地址,printf(函数名),利用vs2013的反汇编功能,汇编中的jmp即是C语言的goto ,参考游戏中,捡宝箱,goto,给服务器发请求,捡到犀牛反坦克战车 void(*p)() = msg msg是另一个定义好的函数,这是函数的间接调用p();这一用法常用于做挂;MessageBoxA的用途
//指针的直接调用和间接调用 声明函数指针后只能赋值函数名(只能传递至)函数指针不能做++ -- 因为没有任何意义
//综合实例,根据用户输入分别执行函数,函数指针必须明确 返回值 参数的数据类型 指针类型必须一致,盟军的转移大法,使用了move函数,该特性还可用于hijack
//=======================返回指针的函数============================
//定义 int *go(){return &b},调用*(go())
//用随机数生成一个数组,并返回最小值的指针,并根据指针修改最小数的值,这一基础技术将在字符串中大方异彩
//char str[40];printf("%s",strcpy(str,"喜欢陈培昌")); -----实现一个自定义的strcpy函数,利用指针原理实现程序窗口控制
//左值int a =5,a即为左值,变量指针也可以为左值;指针常量除外 int *const = px
int a=30,b=6;
printf("a的地址%p,b的地址%p\n",&a,&b);
int *p;
scanf("%x", &p);//输入一个16进制整数,这里把a,b的地址;%x输入后六位,%p输入所有位数
*p = 888;
printf("%d\n",b);
system("pause");
//空指针 可以接收任何类型的指针,用于malloc返回指针的场景,void指针实际作用是快递指针
//注意调用void指针时,要转换成你需要的指针类型
//memset()对内存的每一个字节赋值#include<memory.h> memset(str,‘A‘,5)// num(5)={2,3,4,5}memset(num,0,20)数组清0
//malloc(1024*1024*8)8M内存分配;void(*)p=malloc(1024*1024*20),直接给内存地址赋值
//malloc() return void* in stdlib.h free(p)根据地址释放内存 ;检测内存是否分配成功,是否为空
//malloc精髓,对于一个庞大的文件,可以分配合理的内存空间安放文件的一部分
//编译器把代码翻译成机器指令,静态分配处理不了大数据,容易浪费内存,动态:程序运行时可以随时申请,释放内存
//include<limits.h> void *p = malloc(UNIX_MAX)
//realloc重新分配内存,具备复制原数组到重新分配的内存空间的功效realloc(p,newsize)realloc(已分配内存地址,新分配内存地址),calloc(对象个数,对象所占字节数)尝试定义一个数组,并realloc
//malloc,realloc都是分配内存,但是只有realloc会对分配的内存做初始化
//warning:内存释放后,指针的内容并不发生改变,这时引用指针,会得到垃圾数据,程序也会发生异常,所以软件工程规范,指针应该赋值为空!!!内存不能反复释放,也不要释放一个并未占用的地址,指针赋值为NULL,可以规避反复释放内存,以及指针重复引用的问题
//内存泄露:现在已知释放了动态内存,并不意味着指针会消亡,指针的值会发生改变。所以,如果出现内存未释放,而指向这片内存的指针发生了改变,或消亡就会发生内存泄露的事件,持续的泄露将导致系统的崩溃,模拟一场内存泄露事故。服务器等需要持续运行的程序,尤以此害为甚
//迷途指针,内存清空后,指针仍指向原来那片内存区域,访问时,将打印垃圾数据,解决办法,指针赋值为NULL
//getchar()会被当成一个字符
//32位最大识别4G内存,我有2的32次方字节,每个地址表示一个字节,1024=2的10次方 2的32次方能处理的最大位数就是4GB
//指针存储的值是一个32位的地址,所以一个指针大小是4个字节
//vs2013可以通过配置管理器选择64位,以供编写64位操作系统,64位意味着寻址能力更强(如果配置ARM,可能需要外接设备,且只能使用远程调试器)
//64位模拟32:现在海量数据发展,需要更大内存空间对数据进行处理,虽然内存有4G,但cpu寄存器,显卡现存等硬件也占用内存,所谓32位和64位是地址的位数。做服务器编程一定要用64位。int,double等在64位下占用内存或许更大,这由编译器决定!编程的内存概念和硬件的内存卡是有区别的。2的64次方,使得编译器可以管理海量内存,而且还要很高很快的内存处理能力。
//vs DEBUG模式:带有调试信息,文件很大,只为代码跑起来正确
//vs RELEASE模式:优化版本,比较slim,优化代码,运行速度更快
//程序bug 80%集中在内存,C语言和内存交互需要使用系统特权指令
_asm{
}
//调试代码可能会查看寄存器,和内存信息;CPU分两块 运算器和控制器(把值赋给地址)70%--C,15%---汇编, 15%---C++,指令和数据载入内存,由CPU负责运算
//内存按顺序编号组织起来的空间,以供数据载入,内存数据靠供电完成;内存保存的是二进制数据,CPU执行离不开内存,代码区和数据区,
//内存代码区----程序执行指令
//内存数据去----全局和静态数据
//堆栈----存放临时变量
、、
//内存由一系列小个子组成,每个小格子相差1,每个小格子存储8个二进制位(也就是一个字节)
//变量实际上是对内存地址的抽象
//指针变量---专门存储指针地址的变量,一个变量,存储的是值是指针
//指针----指向内存的地址,但这种说法并不完全,指针是内存的量,不仅仅是地址,还有数据类型
//指针变量初始化的必要性,系统不会清空原来地址上的二进制数据,一旦访问,就有可能造成程序崩溃,所以指针使用前务必初始化。当然vs2013等开发IDE新增了安全检查,但vim 等工具并无相关安全机制
//windows下提示的停止工作往往表明你的指针越界了!企图修改操作系统进程的内存变量
//跨进程修改变量时会用到指针(外挂),函数改变外部变量
//gcc vc 数组都无副本机制
//循环数组时,最好使用指针循环,下标循环可能会导致越界;
//函数return机制 auto变量,函数执行完毕后就消亡了
int get()
{
int a=3;
return a;//这厢将返回到寄存器,而寄存器无法取地址和赋值,如果取了就宕机,有副本机制
}
//函数执行完后,内存会被回收,如果恰好没人使用内存,这片内存仍旧保留原来的内容,如果有人使用过,那么里面必是乱码(代码测试)
//返回地址,一定不能返回栈区地址,static int a=3
//char *p="love cpc love xxd";p存储了字符串的首地址 是常量不可修改char *px =p while(*px!=‘\0‘)
//任意数据类型都可以拆分为基本数据类型,返回的副本放入寄存器,或者是cache(内存和CPU之间的),如果cache不够用了,会开辟一段内存,变成虚拟cache(也禁止取地址),例如结构体可以拆分为基本变量放入cache
//使用指针时,注意数据类型 int*p printf("%d\n",*p) 类型---步长---解析方式
//结构体声明数组的两种方式(*p->name)
*========================================结构体======================================
为了存放多种类型的数据结构而发明的数据结构
原文地址:https://www.cnblogs.com/saintdingspage/p/11966297.html