欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C---指针与整数的加减法&数组地址与整数的加减法---图解篇

程序员文章站 2024-02-29 22:39:28
...

最终学习C/C++,遇到很多疑难杂症。希望用自己的理解和图形化的方式,把核心的问题表达清楚,即使是小白,也能看明白什么原理!(不忘初心,晚上加鸡腿!)

C---指针与整数的加减法&数组地址与整数的加减法---图解篇

  • pa是指针,指向了数组a
  • 数组a有10个元素,都初始化好了
  • int类型的数组,每个元素占用4个字节的大小,内存中每4个字节内存存储了一个元素,共计40个字节大小,右边暂时省略了!
  • 数组名a的值是首元素的地址a[0]的值,虽然a和a[0]表达的不一样,但是值都一样的

1.指针与整数的加减(指针的偏移)

#include <stdio.h>

int main() {

	int* pa;
	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	pa = &a;					// 将指向指针数组a,其实默认指向a[0]这个元素
	printf("%d  \n", *pa);
	printf("%d  \n", *pa + 1);	// 打印数组后面一个元素的值(内存中的概念是:从当前指针所指向的内存单元开始,往后拖动4个字节,然后再取4个字节的值,最终算出这个元素的值)
	printf("%d  \n", *pa + 2);	// 同理,往指针后面移动8个字节之后,再取连续4个字节的内存,算出的值
	printf("================\n");
	pa = &a[2];  				// 将指针指向数组的第三个元素,a[2]
	printf("%d  \n", *pa);
	printf("%d  \n", *pa + 1);	// 
	printf("%d  \n", *pa + 2);
	return 0;
};


如上代码中:pa = &a[2]; 其实就是把指针指向了第三个元素(索引为2),入下图所示
C---指针与整数的加减法&数组地址与整数的加减法---图解篇


1
2
3
================
3
4
5

如上可以说明:

  • 指针指向的数组,其实就是把指针指向数组默认的首元素,通过指针的偏移,就可以找到最终每个元素的值了。(也可以通过a[i]这种方式获取值的大小,但这不是我们将要说明的重点)
  • 指针既然可以指向第一个元素,也可以指向其他元素,那该如何获取前面的值呢?
int main() {

	int* pa;
	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	pa = &a[2];
	printf("%d  \n", *pa);
	printf("%d  \n", *pa + 1);
	printf("%d  \n", *pa + 2);
	printf("=================\n");
	printf("%d  \n", *pa - 1);				// 左偏移1个元素
	printf("%d  \n", *pa - 2);				// 左偏移2个元素
	return 0;
};


C---指针与整数的加减法&数组地址与整数的加减法---图解篇

3
4
5
=================
2
1

2.数组地址与整数的相加减(数组地址的偏移)

#include <stdio.h>

int main() {

	int* pa;
	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	pa = &a;
	printf("%x   \n", &a);
	printf("%x   \n", &a[1]);
	printf("%x   \n", &a[2]);
	printf("%x   \n", &a + 1);
	return 0;
};



3dfe08			// a[0]地址
3dfe0c			// a[1]地址
3dfe10			// a[2]地址
3dfe30			// &a + 1地址

通过结果表明:

  • 相邻元素之间的地址确实相差4个字节,32位系统中,int类型确实占用4个字节大小
  • 3dfe30与3dfe08两个地址相差是40,也就是说,&a+1向右边偏移了40个字节,就是整个数组的长度。(如果数组a的长度为5,那么将移动20个字节)

根据如上的原理,那么如下的代码中,*(p_last - 1),最终能打印什么呢?


int main() {

	int* pa;
	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	pa = &a;
	printf("%x   \n", &a);
	printf("%x   \n", &a[1]);
	printf("%x   \n", &a[2]);
	printf("%x   \n", &a + 1);
	int* p_last = &a + 1;
	printf("%d  \n", *(p_last - 1));
		
	return 0;
};


C---指针与整数的加减法&数组地址与整数的加减法---图解篇

50f6b4
50f6b8
50f6bc
50f6dc
10

根据如上2个案例的说明:

  • int* p_last = &a + 1,说明指针p_last指向的位置,在紧邻着数组a(占用40个字节)的右边,如上图所示位置
  • *(p_last - 1)指针p_last向左偏移4个字节,然后取值,最终查看到的内容为10
  • 上面 (p_last - 1) 如果更换为p_last -1 最终会打印乱码,所以案例一中的原理我猜想也是*(p-1)是最合适的写法

以上案例中:

  • 如果是其他类型的数组,例如char类型数组,则每个字符暂用1个字节,10个字符共计占用10个字节。
  • 如上案例中,左移或右移一个元素,代表内存上移动一个字节,&a+1,也就向右移动了10个字节大小的内存