指针就是内存单元的地址
一维数组:
指针的不同形态,a[i] = p[i] = *(p+i) = *(a+i);
a和p这样的写法是数组名,虽然地址和数组第一个元素的地址一样,但长度为整个数组的长度如sizeof(a/p)= 元素长度 + 元素个数;而a[i] = p[i] = *(p+i) = *(a+i)则为第i个元素的起始地址,但长度为一个元素的长度。
二维数组:
二维数组可以理解为是两个维度,第一维度把一个二维数组的所有元素之和作为元素,长度也是这个二维数组之和,第二维度好比为一维数组,每个元素就是一个元素。
差异:
*(p+1) != *p +1,在一维数组中是不成立的,前者为第二个元素,后者为第一个元素的值加1,但在二维数组中,前者为第二个二维数组的第一个元素起始地址,后者为第一个二维数组的第二个元素的起始地址。
相同,加*都是降维,加&都是升维,维度为最低再降就是值。
指针数组和数组指针:
*p[a]是指针数组,(*p)[a]是数组指针,关键是后两个字,原理是看*修饰的是谁。指针数组是个数组,它的元素还是数组元素,可以赋值。但是数组指针,它的元素是以数组的形式存放的是指针,不可以赋值,只可以传地址。
const修饰用法:
const Int *p;可以给地址,如 p = &m;但是不可以修改地址内容,如(*p)++;
但是int *const q;不可以 q =&m;×只能在定义时赋地址,如int *const q =&m;//即使赋相同的地址,也不行。但是*q = 20,可以,
const就近原则,后面跟谁谁不可以改。修饰类型则数值不能改,但地址可以改;修饰指针时只可以改,但地址不可以修改。
#include <stdio.h>
int main(int argc, char *argv[])
{
int m = 10;
double n = 3.14;
void * p, * q;
p = &m; //(void *)&m;
printf("%d %d\n", m, *(int *)p);
printf("%p\n", p);
p++;
printf("%p\n", p);
q = &n; //(void *)&n;
printf("%.2lf %.2lf\n", n, *(double *)q);
printf("%p\n", p);
q++;
printf("%p\n", q);
return 0;
}
运行结果为
10 10
0x7ffe16e9f78c
0x7ffe16e9f78d
3.14 3.14
0x7ffe16e9f78d
0x7ffe16e9f791
以上这段代码是void类型的指针,虽然用的少,可以根据以上代码进行了解,待到用时可以快速帮助解决问题,但是尽量少用。
函数及函数指针:
无疑函数指针是个指针,存放的是内存单元的地址。
但是它们都涉及传值和传址,传值则不会改变实参的数值,传址是可以改变原来的数值的,但是改变不了所传地址,原理是给相应的内存地址空间赋值来改变数据的值。
个人猜想,根据“升维原则”(个人理解),如果有二维传址,有可能就能改变一维的地址了吧。