指针的原理——地址内存

Posted 张同学吧

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了指针的原理——地址内存相关的知识,希望对你有一定的参考价值。

指针

指针是什么

百度百科:
指针,是C语言中的一个重要概念及其特点,也是掌握C语言比较困难的部分。指针也就是内存地址,指针变量是用来存放内存地址的变量,不同类型的指针变量所占用的存储单元长度是相同的,而存放数据的变量因数据的类型不同,所占用的存储空间长度也不同。有了指针以后,不仅可以对数据本身,也可以对存储数据的变量地址进行操作。
指针是一个占据存储空间的实体在这一段空间起始位置的相对距离值。在C/C++语言中,指针一般被认为是指针变量,指针变量的内容存储的是其指向的对象的首地址,指向的对象可以是变量(指针变量也是变量),数组,函数等占据存储空间的实体。

由百度百科可知,指针的实质就是内存的地址,在计算机的内存中,每一个字节都有自己的地址,内存地址是一种用于软件及硬件等不同层级中的数据概念,是用来访问电脑主存中的数据。利用指针中存放的地址可以直接指向(points to)存在电脑存储器中另一个地方的数据。由于通过地址能找到所需的数据,就可以说,地址指向该数据。因此,将地址形象化的称为“指针”,意思是通过它能找到以它为地址的内存单元,并且可以访问内存其中的数据。
在这里插入图片描述

可能听起来比较晦涩,那我就来简单举个例子:如上图,我定义了一个整型变量a整型指针变量p,把a取地址赋值给p。输出p的值,可以看到是133fb5c,这就是变量a的地址,而指针p则是来存放a的地址的变量,也就是指针变量。在这里插入图片描述
在这里插入图片描述

而关于内存更详细的内容大家可以去看参考《程序员的自我修养》,其中第十章 内存中有更详细的内存布局。
我们可以通过指针p来找到a的内容,并且可以直接修改。我们就说p指向了a。指针变量的内容存储的是其指向的对象的首地址(如上),指向的对象可以是变量(指针变量也是变量,也就有了二极指针、多级指针,下面再说),数组,函数等占据存储空间的实体。

指针与指针类型

就和变量的数据类型一样,指针变量也有相应的类型。
在上面的例子中我们还可以发现,输出p+1时,地址增加了4个字节,而不是一个。指针向前走一步或者向后走一步需要走多大,是由指针变量的类型决定,因为指针pint型,所以p+1向下走了四个字节。但是无论指针变量的类型是啥,在32位的机器里指针变量的大小都是 4个字节

int main()
{
	int n = 10;
	char* pc = (char*)&n;
	int* pi = &n;

	printf("%p\\n", &n);//n的地址
	printf("%p\\n", pc);//变量pc的存储的值
	printf("%p\\n", pc + 1);//pc的下一个指针位置
	printf("%p\\n", pi);//变量pi的存储的值
	printf("%p\\n", pi + 1);//pi的下一个指针位置
	return  0;
}

运行结果
总结:指针的类型决定了向前移动或向后移动走一步要多大(几个字节)。

指针的解引用

int main() {
		int n = 0x11223344;
		char* pc = (char*)&n;
		int* pi = &n;
		*pc = 0;   
		*pi = 0;   
		return 0;
}

执行完 * pc=0;之后:
执行完*pc = 0;
执行完 * pi = 0; 之后
执行完*pi = 0;
总结:指针的类型决定了对指针解引用的时候有多大的权限(也就是能操作几个字节)。比如:char* 的指针解引用就只能访问一个字节,而 int* 的指针的解引用就能访问四个字节。

指针运算

指针±整数

重置数组为0:

float values[5];
float *p;
for (p = &values[0]; p < &values[5];)
{
     *p++ = 0;
}

但是有一点要注意,计算器有一种标准:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较
假如这就是我们内存当中所存的数组元素,array[0]是数组的第一个元素,而array[3]则是数组中最后一个元素。这种情况下,指向内存位置的指针是可以和它后面这一块内存比较的,其实就可以理解为一个前开后闭的区间[start,end)。
在这里插入图片描述

所以我们不能这样写:

for(vp = &values[N_VALUES-1]; vp >= &values[0];vp--)
{
    *vp = 0;
}

虽然这样写不会报错也可以运行,但是标准并不保证他可行,而且在不同的编译器下,它运行结果也不一样,所以结果没有意义。

指针-指针

得到字符串的长度

int my_strlen(char*s)
{
	char*p=s;//s的首地址赋值给p
	while(*p!='\\0')
	{
		p++;
	return p-s;//返回值为字符串的长度:空字符的地址减去s的首地址的长度
	}
}

指针与数组

点击链接查看

以上是关于指针的原理——地址内存的主要内容,如果未能解决你的问题,请参考以下文章

C 语言内存四区原理 ( 常量区示例 | 不同函数返回的相同字符串的指针地址相同 )

CUDA:统一内存和指针地址的变化?

C 语言内存四区原理 ( 栈内存与堆内存对比示例 | 函数返回的堆内存指针 | 函数返回的栈内存指针 )

20160206.CCPP体系详解(0016天)

C 语言实现多态的原理:函数指针

20160206.CCPP体系具体解释(0016天)