指针本质论 指针是一个变量,是用来存储地址的变量。这就是指针的本质。 有人可能很纳闷,指针为什么一定要定义成某类型(int, char)呢,不能就是“指针类型”吗?接触过汇编的就容易理解为什么。存储单元的单位是字节,对一个地址进行操作(读取或赋值)就要指明是对单个字节、两个字节、还是双字(四字节)。同样,指针是存储地址的,说白了,指针就是一个地址,自然也要说明了;而且,这个类型还关乎指针自加自减时真正加减的字节数。 顺便说一下,数组名也是指针,数组在申请空间时数组名存储该存储空间的首地址,注意数组名存储的是地址,因此也是指针,只是该指针一旦赋值后就不能修改,即所谓常指针。*************************** 如下函数希望为指针p申请空间,但不能达到目的,为什么呢?void GetMemory(char *p){ char *s=NULL; s= (char*)malloc(100*sizeof(char)); p=s;} 归根结底,C函数形参实参之间只是“值传递”:当形参是普通变量时,传递的是实参的值;当形参是指针时,传递的是指针变量的值,即某变量的地址,这样,可以通过指针成功的改变其所指单元的值,但自身的改变不会传回给实参。上例可改为:void GetMemory(char **p){ char *s=NULL; s= (char*)malloc(100*sizeof(char)); *p=s;}注意这样修改后,调用时实参应该是指针的“地址”(或指向指针的指针)。 见下例,Test函数可以成功修改a[0]的值,尽管形参a的值发生了变化,但不会改变实参a的值,这就说明指针形参的改变不影响指针实参的改变,但通过形参指针修改了其所对应的存储单元的值是,这改变将影响到实参。#include <iostream>using namespace std;void Test(int *a){ *(a++) = 5; //该函数真正所做的修改:将a所指存储空间的值赋为5,并将a值加1 cout<<"调用Test函数结束时:"<<"a = "<<a<<", a[0] = "<<a[0]<<", a[1] = "<<a[1]<<endl;};int main(){ int a[]= {1,2,3}; cout<<"Test函数的关键代码为:*(a++) = 5;"<<endl; cout<<"调用Test函数前:"<<"a = "<<a<<", a[0] = "<<a[0]<<", a[1] = "<<a[1]<<endl; Test(a); cout<<"调用Test函数后:"<<"a = "<<a<<", a[0] = "<<a[0]<<", a[1] = "<<a[1]<<endl; return 0;}; ***********************指针遍历数组举例:#include <iostream>#include <iomanip>using namespace std;int main(){ int array3[2][3][2]={{100,101,102,103,110,111},{112,113,120,121,122,123}}; /***********指针写法,C中是按行优先存储的************/ cout<<array3<<endl;//输出首址 int *p; p = (int *)array3; while(p <= &array3[1][2][1]){ cout<<setw(8)<<*(p++); } cout<<endl; /*********常规写法,三重循环***********/ int i, j, k; cout<<&array3[0][0][0]<<endl;//输出首址 for(i = 0; i < 2;i++){ for(j = 0; j < 3; j++){ for(k = 0; k < 2; k++){ cout<<setw(8)<<array3[i][j][k]; } } } cout<<endl; return 0;}

评论