指针不断的改变指向和多个指针操作一个内存空间
首先这里强调一个问题就是假设我现在知道一个内存地址0xaa11 我怎样将这个地址直接给一个指针呢? 首先这样是没有语法错误的 确实也是这样定义的 但是地址我们是不能随便规定的 这个主要用于程序开发中我们向特定的地址(我们已知的地址)去写入数据(例如:通过I2C接口发送到MCU一个地址数据(unsigned char AdData),一个待写入数据(unsigned char DaData)。)
希望将DaData的值写到MCU内存地址为AdData的寄存器当中。
#include<stdio.h>
void main()
{
int * pReg; // 创建一个指针变量
pReg = (int *) 0xaa11; // 将给定的寄存器地址付给指针
*pReg = 1;
printf("p:%s",pReg);
printf("*p:%s",*pReg);
}
某些编译器在直接赋值也是可以通过的
p = 0xaa11;
但是我随便给一个地址去运行大多数情况肯定会宕机
这个现在只需要了解这种写法
关于我们可以直接利用c语言操作内存:
首先,要确认这部分内存是存在的,如果不存在要申请指定地址的内存空间。其次,要获取修改权限,不论是别人的进程还是我们自己的进程都要拿到权限才能执行操作。最后,关于是否要进内核,这要看对方有没有写防护了,如果在内核层面写了保护,那肯定要进内核才能解决问题了。如果没有保护,或者三环的保护,三环内的代码就能搞定。
还有一种靠谱的说法就是 会修改虚拟内存 也就是偏移后的内存地址 肯定不会是真的内存地址 这个其实也跟操作系统有关系 所以理解没必要去深究了
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
int i;
int j = 0;
char buf[128];
char *p1 = NULL;
char *p2 = NULL;
p1 = &buf[0];
p1 = &buf[1];
p1 = &buf[2];
for(i=0;i<10;i++)
{
p1 = &buf[i];
}
p2 = (char*)malloc(100);
strcpy(p2,"abcdefg123");
for(i=0;i<10;i++)
{
p1 = p2 + i;
printf("%c ",*p1);
}
free(p2);
p2 = NULL;
}
间接赋值(*p)
一级指针应用
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
int a = 10;
int *p = NULL;
//修改a的值
a = 20;//直接修改
p = &a;
*p = 30;//间接修改a的值
printf("a:%d",a);
}
这些都属于最简单的写法 前面的博客也有过介绍
指针在这里两个应用就是可以通过一个函数修改多个值
f1(int *p, int *p2, ...)
{
*p1 = 1;
*p2 = 2;
...
}
这种写法很重要 当然将多个数据封装成结构体也可以将多个改变返回
因为指针是直接将所指向的内存空间修改 就不涉及变量间的操作 而你使用类似于这种操作时本质上并未改变a的值
f2(int a)
{
b = 2;
return b;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int *p;
f1(int *p)
{
*p = 1;
return 0;
}
f2(int a)
{
int b;
b = 2;
return b;
}
void main()
{
int a = 0;
int f1(int *p);
int f2(int a);
f1 (&a);
printf("a:%d\n",a);
f2 (a);
printf("a:%d\n",a);
}
f(int b)
{
...
}
基本等价于
f()
{
int b;
...
}
唯一的区别是f(int b)这种写法int b具有对外属性 可以通过主函数对它进行初始化
第二个应用就是利用指针快速多个的操作与运算 对于子函数与主函数之间的分层意义重大
//函数调用时,形参传给实参,实参取地址传给形参 在被调用函数里面使用*p,来改变实参,把运算结构传出来
//不同的函数通过指针同时操作一块内存空间
函数参数==》接口的封装和设计==》模块的划分==》软件的分层
间接赋值成立的条件和应用场景
1.定义两个变量
int a;
int *p;
2.建立关联
p = &a;
3.通过*p修改内存
*p = 0;
这三个条件自由的组合产生重要的语法现象
1.1 2 3 写在一个函数
2.1 2 写在一起 3写在另外一个函数 (函数调用)
.3.1 单独写 2 3 写在一起 c++里会应用
从一级指针到二级指针
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void f(char **p2);
void f(char **p2)
{
*p2 = 400;
}
void main()
{
int *p1 ;
char **p2 = NULL;//char*是char型的 针变量 ;har**p2是char型的指针变量 的指针变量
//直接修改p1的值
int *p1 = (int *)0x0012ff2c;
//间接修改p1的值
p2 = &p1;
*p2 = 100;//间接赋值,p2是p1的地址
printf("p1:%d\n",p1);
f(&p1);
printf("p1:%d\n",p1);
}
这段代码不一定能够运行 原因看开头我们这里的地址不一定是我们可以修改的地址
这是讲解一下这种写法与内在的意义
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
f(char **p1, int *len1, char **p2, int *len2)
{
char *tmp1,*tmp2;
tmp1 = (char*)malloc(100);
strcpy(tmp1,"111222");
*len1 = strlen(tmp1);
*p1 = tmp1;
tmp2 = (char*)malloc(100);
strcpy(tmp2,"aaabbb");
*len2 = strlen(tmp2);//strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')。
*p2 = tmp2;
return 0;
}
void main()
{
int ret;
char *p1 = NULL;
int len1 = 0;
char * p2 = NULL;
int len2 = 0;
ret = f(&p1,&len1,&p2,&len2);
if(ret != 0)
printf("fail");
printf("p1 : %s\n",p1);
printf("p2 : %s\n",p2);
if(p1 != NULL)//释放p1内存
{
free(p1);
p1 = NULL;
}
if(p2 != NULL)//释放p2内存
{
free(p1);
p2 = NULL;
}
}
从二维到多维
这样我们可以推出 用n级指针形参,去修改n-1级指针(实参)的值
指针做函数参数,问题的实质不是指针,而是看内存块,内存块是 1 维、2 维。
1)如果基础类 int 变量,不需要用指针;
2)若内存块是 1 维、2 维,需要指针。