#include <stdio.h>
void f(int *q);
main()
{
int a[5]={1,2,3,4,5},i;
f(a);
for(i=0;i<5;i++)printf("%d",a[i]);
}
void f(int *q){
int i=0;
for(;i<5;i++)(*q)++;
}
这段代码的输出为什么是
6,2,3,4,5
而不是2,3,4,5,6呢?
f(a)是将数组首地址传送过去,所以执行时f函数中q的值是数组首地址即是a[0]的地址,由于你没有对q进行操作,所以函数里实际执行的是把a[0]自增5次,得到的结果自然就是6,而后面几个元素没有改变。你应该写成这样:
for(;i<5;i++)
{
(*q)++;
q++;//指针指向下一元素
}
作者:夜月
链接:https://zhuanlan.zhihu.com/p/37790070
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
开始之前,我只想重复一句话:计算机底层一切都是数据;计算机底层一切都是数据;计算机底层一切都是数据。嗯,重要的事情说三遍。 汇编语言,是使用一系列指令集,通过操作寄存器以及内存单元,从而达到操作CPU的目的的语言。 汇编语言想要操作寄存器以及内存单元,就必须先要对其编码,以免引起数据引用的混乱,于是就有了内存单元地址与寻址,内存单元通常是一字节一个地址,他包含了我们通常所说的内存、CPU缓存、以及网卡和显卡的缓存。为了区分不同的数据,初始化寄存器时,又把寄存器分为了栈地址寄存器、代码地址寄存器以及数据/地址寄存器。额,用专业点的说法应该是栈指针寄存器、代码指针寄存器以及数据指针寄存器。 为了读入鼠标、键盘的输入以及系统错误的处理等等,人们把一些汇编代码以数据的形式存储在内存中,并且专门开辟出一段空间用来存储这些汇编代码所在的地址,这就是中断以及中断向量表。 为了不碰这部分敏感数据,根据操作系统动态分配内存,满足跨平台的要求,所以C语言引入了指针以及指针变量。说白了就是指针,其实是抽象的产物,C语言利用指针来表示对一组或者一块内存空间的寻址。举个例子,整形变量占用四个字节,声明整形变量的时候操作系统会分配四个字节,并保存起始位置的地址,再把起始位置的地址与变量名关联,之后我们执行寻址操作时,就是取与变量关联的地址对应的内存单元。 指向结构、函数以及指针的指针也是同理。数据指针以及代码指针在底层级别唯一的不同就是编译之后使用的指针寄存器不同。 至于全局变量和局部变量在汇编,也就是底层级的表示就是,使用指向函数的代码指针跳转到函数所在内存单元执行操作,结束后返回主函数,但是在调用函数之前,操作系统会把一些数据保存,比如当前函数指针以及变量指针等等,通常是保存在栈中,而在被调函数执行完毕,返回主函数之前,操作系统会把被调函数的初始位置指针以及变量指针保存,直到程序执行完毕释放或者被别的数据覆盖。所以全局变量和局部变量的传值必须使用寻址方式,也就是使用指针。