c语言指针进阶(二)

 

 

指针不断的改变指向和多个指针操作一个内存空间

首先这里强调一个问题就是假设我现在知道一个内存地址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 维,需要指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值