C语言指针,及指针识别能力

指针的基本意义

在创建变量时 *号和变量名结合,不和类型名结合
编译器在编译时,是从右到左识别的,哪怕在定义时

(int*)p,s;

这样写也是错误的,这样的写法编译器会识别为强转功能,但是p和s并没有初始化,自然也就无法进行强转
强转的写法是:

int a=0x12345678;
int *ip=&a;
char *cp=(char*)&a;
char *p=(char*)&a;
*p='a';
p=p+1;
*p='b';
p=p+1;
*p='c';
p=p+1;
*p='d';
p=p+1;

要明白上面的程序首先我们要明白小端存放的原理
小端存放
通过这个程序我们可以知道不同类型转换时,替换值的过程,建议通过编译调试来看看
这里p=p+1;因为是char*类型,所以只移动了一个字节。而且高位数存放在高地址,低位数存放在低地址,所以从低位数开始改变
ps:p=p+1 相当于p=p+sizeof(char)*1;
*p=‘a’;
在这里插入图片描述
*p=‘b’;
在这里插入图片描述
*p=‘c’;
在这里插入图片描述
*p=‘d’;
在这里插入图片描述

我们也不能做这样的操作

int *p;
p=&10;

这样也是不对的,在给p传地址时,我们不能对常量取地址

int p=&a(将a的地址传给p,而不是p)
指针类型的大小是4字节

例如

int a=10;
int b=20;
int *p=NULL
p=&a;	这里我们要注意,这是*p是a,而不是10,a才是*p的指向,只不过a被赋值为10罢了
*p=100;
p=&b;
*p=200;

为了解释指针的值的问题,在这我假设a的地址时0x0012ff28,他存放的是10,b的地址是0x0012ff1e,存放的是20。p的地址是0x0012ff10,存放的是a或b的地址0x0012ff28/0x0012ff1e,这要看程序员将谁的地址给了p。
那么有下面的几个等式
&p=0x0012ff10;
p=0x0012ff28/0x0012ff1e;
*p=a/b
*p=100(相当于给a赋值为100)

另外引入另一个知识,关于数在内存中存放的问题。以及指针识别能力问题

double x=12.32;
int a=10;
char y='a';

由于x86系统采取的是小端存放,所以一般以其地位地址所谓某类型变量的首地址。
我画图来解释。在这里插入图片描述
以此类推,可知++p或者p++或者p+1这些加的都是对应类型的字节数。
那么自然有可能发生
char *p
int *p
double *p
的指针同时都指向了0x0012ff00,虽然都指向了地位的第一个地址,但是代表的意义不同
虽然指针类型的大小是4字节
但是每个类型的指针的识别能力是有限的,比如char型的指针,每次只识别内存中的一个字节来确定char的值,int类型的指针会识别4字节内存来确定int的值。而double会识别8个字节的地址。要注意,不同类型的指针不能相互赋值

还要注意我们在使用指针是切记不能定义野指针
我们需要注意的是,我们需要区分野指针和失效指针,我举个例子来讲解
如int *p;
这是上面的指针p就是野指针,我们为指针p开辟了一个4字节的内存空间,但是我们没有给这个指针添加指向。那么我们无法知道指针p的指向。
而 失效指针
比如

void *fun()
{
  int a=100;
  return &a;
}

当这个函数使用完毕后,返回的指针变为了失效指针,它依旧指向原来的空间,但是那块空间依旧失效没有了原来的主人。那么即使得到了原来的结果,在实际上也是没有意义的

int *p;//没有对象的指针

解决野指针的方法有

int *p=NULL;//令其为空
int *p=&a//给他一个对象

同时我们还要知道指针的下标操作
比如char *p = “abcdef”;
此时p[2]值 为’c’。而p表示字符串"abcdef"的首地址,*p的值则相当于p[0],值为’a’。
如果我们在函数中要调用指针,在使用前我们必须要进行判空操作

if(p==NULL);

首先要知道指针都是四字节的
下面举一个例子
可以让我们知道指各种类型指针的加一的范围

char a3, a2, a1, a0;
	char *p3, *p2, *p1, *p0;
	char **s;
	//假设 a3, a2, a1, a0和*p3, *p2, *p1, *p0存放的内存空间都是连续的,并且s指向p
	//求s+1  =4字节
	//*s+1   =4字节
	//**s+1  =其本身的数加一
	s+1=s+sizeof(type*)*1;//二级指针+1,指的是指针,+1加指针类型的4个字节
	*s+1=s+sizeof(type)*1;//一级指针+1,指的是不同的类型变量,+1加的是指向类型的字节数
	**s+1=数值加一//就是数值加一

接下来要说明指针变量在和0,NULL比较是的方式
指针变量作为if的判断条件时,同样有三种方式
A:if(p==0) if(p!=0)
B),if(p ) if(!p);
C) ,if(NULL == p); if(NULL != p);
哪一组或是那些组正确呢?我们来分析分析:
A)写法:p 是整型变量?容易引起误会,不好。尽管 NULL 的值和 0 一样,但意义不同。
B)写法:p 是 bool 型变量?容易引起误会,不好。
C)写法:这个写法才是正确的,但样子比较古怪。为什么要这么写呢?是怕漏写一个 “=”号:if(p = NULL),这个表达式编译器当然会认为是正确的

最后介绍一下普通的利用指针识别能力的特质完成数据打包和解析

int main()
{
    int a = 3;
    int c = 'x';
    float f = 3.14f;

    char buffer[20];

    // 在下面实现打包代码
    *((int*)buffer) = a;
    *(buffer + sizeof(int)) = c;
    *((float*)(buffer + sizeof(int) + sizeof(char))) = f;

    // 在下面实现解包代码
    printf("a = %d\n", *((int*)buffer));
    printf("c = %c\n", *(buffer + sizeof(int)));
    printf("f = %f\n", *((float*)(buffer + sizeof(int) + sizeof(char))));

    return 0;
}

所以同理也可以这么做

	int arr[3] = { 1, 2, 3 };
	int x = 10;
	*((int*)arr) = x;

它的另一种写法为:

    // 在下面实现打包代码
    int *pi = (int*)buffer;
    *pi = a;

    char *pc = (char*)(pi+1);
    *pc = c;

    float *pf = (float*)(pc+1);
    *pf = f;

    // 在下面实现解包代码
    printf("a = %d\n", *pi);
    printf("c = %c\n", *pc);
    printf("f = %f\n", *pf);

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值