指针是一个变量,所不同的是,它存的是地址。
因为数据类型决定着如何解释这个地址(字节数和操作),因此根据的数据类型的不同,指针又有不同的类型。
某个对象(a)的地址范围为:[&a, &a + size_n),其中size_n是a所占的字节数
比如一个一维数组int a[10],地址范围为[&a, &a + 10*sizeof(int) )
对于不同的数据类型,操作是不同的,
如一维数组指针和二维数组指针: int a[3], b[4][3], *pa = a, (*pb)[3] = b;
对于
pa += 1 和 pb += 1
是不同的。前者会移动sizeof(int)个字节,后者则会移动3*sizeof(int)个字节,这就是数据类型决定操作,所以我想这应该就是设计不同类型的指针的主要原因了。
关于多维数组的地址
众所周知,一维数组的元素地址是连在一起的,二维数组是根据列优先排列的,也就是一行接一行排列。实际上,对于多维数组,下标越靠右,下标变化得越快
一个m维数组a[N1][N2]...[Nm]
则有
其中size是元素的所占字节数
注意这里的单位是字节,因此不是并不能直接在C语言里使用
例如int a[3][4];
&a[i][j] = a +sizeof(int) * i * 4 + sizeof(int) * j
正确的调用a[i][j]地址的C语法为 (int*)a + i * 4 + j
关于void类型指针
前面说过,数组类型决定如何解释这个地址,void并不是一种真正的类型。因此它不能直接使用,但它可以作为一种中间量,暂时保存地址。真正使用的时候必须转换。
它常常作为通用指针使用。在C标准库里面,有的函数参数正是这种,这样就可以实现通用操作。
如:void *memcpy( void *to, const void *from, size_t count );
这里的count是数据类型的所占的字节数,这样可以实现任意的类型的复制操作
关于字符串的地址:
字符串一般有两种保存方式,
(1) char str[] = {“123456789”};
(2) char *str = “123456789”;
第一种是使用字符串数组保存,文字是存在str数组里的,
第二种则不同,str是一个字符指针,因此它保存的仅仅是这段文字存放的位置的首地址,这段文字是存在常量区的。
另外,还可以先申请一段空间(堆),使用malloc等,然后保存文字,这样也是也可以的,而且更灵活,相对的也更容易出错。