道不尽的“指针”和“数组”

来源:互联网 发布:windows linux 多线程 编辑:程序博客网 时间:2024/05/16 01:07

1. 一个基本的数据类型(包括结构体等自定义类型)加上“*”就构成了一个指针类型的
模子。这个模子的大小是一定的,与“*”前面的数据类型无关,“*”前面的数据类型
只是说明指针所指向的内存中存数的数据类型。所以在32位系统下,不管是什么样的指针
类型,其大小都是4byte,void *也不例外。

2. 以指针的形式访问和以下标的形式访问:
例如:
char *p = "abcdef";
定义了一个指针变量p,p本身占四个字节,p里存储的是一块内存的首地址。
我们如果需要读取字符'e'有两种方式:
a. 以指针形式:*(p + 4),先取出p里存储的地址值,假设为0x0000FF00,然后加上
4个字符的偏移量,得到新的地址0x0000FF04。然后取出0x0000FF04地址上的值。
b. 以下标的形式:p[4],p[4]这个操作被解析成:先取出p里存储的地址值,然后加上
中括号中4个元素的偏移量,计算出新的地址,然后从新的地址中取出值。
也就是说:以下标的形式访问在本质上与以指针的形式访问没有本质区别,只是写法上不同罢了。

char a[] = "123456";
定义了一个数组a,a拥有7个char类型的元素,其空间大小为7。
a.以指针形式:*(a + 4),a这个时候代表的是数组元素的首地址,假设为0x0000FF00,
然后加上4个字符的偏移量,得到新的地址0x0000FF04,然后再取出0x0000FF04地址上的值。
b. 以下标的形式:a[4],a[4]这个操作会被解析成:a作为数组首元素的首地址,然后加上中括号中
4个元素的偏移量,计算出新的地址,然后从新的地址中取出值。
需要说明的是,以上的偏移量的单位是元素的个数而不是byte数。
通过上面的例子,我们似乎感觉数组和指针说的是一回事,但是,我们要记住:
数组就是数组,指针就是指针,他们是完全不同的两码事,他们之间没有任何关系,只是
经常穿着相似的衣服来迷惑你罢了。

3. 一个问题:
int a[5] = {1,2,3,4,5};
int *ptr = (int *)(&a + 1);
这个时候ptr指向哪个数?
对指针进行加1操作,得到的是下一个元素的地址,而不是在原有地址值上直接加1。
所以,一个类型为T的指针的移动,以sizeof(T)为移动单位。
&a + 1:取数组a的首地址,该地址的值加上sizeof(a)的值,即&a + 5*sizeof(int),
也就是下一个数组的首地址,显然当前指针已经超过了数组的界限。

假如把a和ptr的地址,还有*ptr打印出来(16进制):

31fa44
31fa58
-858993460

我们发现58-44=14,转化成10进制正好是20(5*4,5个int)。

0 0
原创粉丝点击