【C语言】指针运算

在学习指针时,说指针也是一种变量,所以指针变量就和普通变量一样:需要占用内存,需要初始化等等。但在使用和普通变量一样的用法时,指针变量的运算就和普通变量的运算不太一样了。

 

一:

先给出一个例子吧。

#include <stdio.h>

int main()
{
	int arr[10]={1,2,3,4};
	int *p=arr;
	printf("%d\n",*p);//这时*p是arr[0]的值
	*p=10;//这时*p将arr[0]的值从1改为10
	printf("%d\n",*p);
	p++;//在这就会有人问p++是指什么?
	*p=20;
	printf("%d\n",*p);
        printf("%d\n",arr[0]);
        printf("%d\n",arr[1]);
	return 0;
}

 

我们可以想一下加法都有哪几种可能情况?
1.加一个字节
2.加一个数组
3.加一个单元格

 

在上面的程序中有定义一个数组arr,假设数组的起始地址是1000,因为定义的是一个整型数组,所以每一个单元格是4个字节,那么arr[1]的地址是1004。所以就会有下图:

 

 

 

 

 

 

 

*p=10;这句是将arr[0]的值变为10

 

1.当假设p++是指加一个字节:

 

因为数组中每一个单元格是4个字节,所以可以把前两个单元格放大,整型数字在计算机中是以“0”,“1”代码的形式存在的,但是过长的数字代码对人的阅读造成了较大的障碍,为了解决这一问题,才使用十六进制来表示二进制,4位二进制数用1位十六进制数就可以表示,十进制数10用十六进制表示为0xa,但是要用a占4个字节,也就是8位,所以是0x0000000a,那么十进制数2用十六进制表示为0x00000002。因为在计算机内有大端模式和小端模式保存字节。大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在高地址中。小段模式,是指数据的高字节保存在高地址中,而数据的低字节保存在内存的低地址中。在英特尔处理器,Windows操作系统上,控制台显示的结果是99 FB E4 15,与直接求出来的十六进制值15 E4 FB 99 正好相反,所以证明是小段的。所以就有如下图:

 

 

 

所以在当p++表示为加一个字节时,然后把*p赋值为20,则会有:

 

 

 

此时arr[0]表示的十六进制数是0x140a,转换为十进制是5130,arr[1]为0。很显然不符合实际。

 

2.当假设p++表示加一个数组:

 

刚开始指针p指向的是arr[0],然后p++就直接由一个数组头跳到数组尾,此时指针p对于数组来说没有用。

 

 

3.当p++表示加一个单元格:

 

这时当p++之后指针p指向的是arr[1],就会有如下图:

 

 

 

此时得到的arr[0]的数用十进制表示是10,arr[1]的数用十进制表示为20,是符合我们的认知。

 

所以上面程序的运行结果是:

 

所以对于整型指针变量加1,是指加一个单元格的长度,也就是4个字节。这个同样也用于其他类型的指针变量。当是字符指针变量p,p++是指加一个单元格的长度,也就是1个字节.因此,指针加整型数字时是需要调整,调整的权重是sizeof(指针去掉一个*)。

 

例如:

int main()
{
	int *p = (int *)1000;
	printf("%d\n",p+5);//1020
	printf("%d\n",(short *) p+5);//1010
	printf("%d\n",(unsigned long *)p+5);//1020
	printf("%d\n",(double *)p+5);//1040
	printf("%d\n",(char ***)p+5);//1020
	printf("%d\n",(char *)p+5);//1005
	printf("%d\n",(long long)p+5);//1005

	return 0;
}

运行结果是:

 

 

 

 

 

二:指针减整型数字和加整型数字类似

 int main()
{
	int arr[10] = {0};//x
	int *p = &arr[9];//x+36
	int *q = &arr[1];//x+4
	printf("%d\n",p-q);//8
	printf("%d\n",q-p);//-8
	printf("%d\n",(short *)p-(short *)q);//16
	printf("%d\n",(long *)p-(long *)q);//8
	printf("%d\n",(char **)p-(char **)q);//8
	printf("%d\n",(double *)p-(double *)q);//4
	printf("%d\n",(long long)p-(long long)q);//32
	printf("%d\n",(char *)p-(char *)q);	//32

	return 0;
}  

执行结果如下:

 

 

 

三:指针加指针:是非法的

 

四:指针减指针:是求两个指针间隔的单元数

1.算出字节数;2.再除以调整的权重

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值