指针以更接近机器的方式表示地址,所以会更有效率
一个贯穿指针与数组的概念:数组名是数组首元素的地址
首先是指针的概念:
int* p; //定义一个指向int的指针
int n = 3;
p = &n; //赋值
printf("p=%x\n&p=%x\n*p=%d\n&n=%x\nn=%d",p,&p,*p,&n,n );
p=eff7ac //指针的值是所指向对象的地址
&p=eff7b8 //指针本身的地址
*p=3 //指向对象的值
&n=eff7ac //对象的地址
n=3 //对象的值
数组的指针表示法:更接近机器表示
int s[4] = { 12,5,1,6 };
printf("s[2]=%d\n*(s+2)=%d\n&s[2]=%x\ns+2=%x",
s[2], *(s + 2), &s[2], s + 2);
s[2]=1 //数组表示法
*(s+2)=1 //注意*(s+2)和*s+2的区别,且只有s是指针变量才有s++这样的表达式
&s[2]=d5fcd8
s+2=d5fcd8
数组可以用指针表示,但不代表数组名就是指针,指针可以代表数组名,例如:
int s[4] = { 12,5,1,6 };
int* p = s;
printf("size of s:%d\n",sizeof(s));
printf("size of p:%d", sizeof(p));
p并不是数组本身,而是指向s数组的指针
size of s:16
size of p:4
注意:
int s[4] = { 12,5,1,6 };
int* p = s;
printf("%d", *p++);
12
//*和++优先级相同,但是结合律从右往左,所以先求p++,但是这个操作要到printf("%d",
*p++);整条语句结束才会生效,所以*p的值依旧是12,
再看一个:
int s[4] = { 12,5,1,6 };
int* p = s;
printf("%d %d", *p++, *++p);
5 1
printf("%d %d", *++p,*p++);
1 12
我用的是VS2017,不同系统可能会有所不同吧
从这两个语句大概猜出了printf函数的工作原理:应该是一个栈,从右到左入栈,期间计算p,
再出栈输出,这样就能解释的通了,这种语句以后还是少写
指针与多维数组
int s[4][2] = { {2,4},{5,6},{7,8},{9,3} };
printf("%p %p %p %p", s,s[0],*s,&s[0][0]);
004FF7F8 004FF7F8 004FF7F8 004FF7F8
之前说过s是数组首元素的地址,s的首元素是一个内含2个int的子数组,s[0]是一个占用一个
int大小对象的地址,由于数组都开始与用一个地址,即s[0]和s的值相同
*s就就表示数组首元素的值(s[0]),s[0]本身就是int类型值的地址,该值地址就是&s[0][0]
再看一个例子:
int s[4][2] = { {2,4},{5,6},{7,8},{9,3} };
printf("%d", *(*(s + 2) + 1));
8
其实&和*就像是脱衣服和穿衣服似的关系