指针是什么? 是地址。这个大家都知道。但是理解得未必深刻。我们以一条条活生生的代码来分析。 int *pointer; 声明一个指针。 pointer是一个指向Int型的指针的变量。 而变量里面的值是一个内存地址(在大部分操作系统中不是物理地址,是经过地址映射后的虚拟地址)。 而这个pointer只在程序文件(.c,.cpp)里存在,当编译成可执行文件后,它被替换成一个难看的符号,比如LLC012什么的。这点与java相反,所以C程序是没有办法反编译的。 当运行一个C程序时,操作系统分配给LLC012一块32位大小内存地址,以后你改变指针的值时,改变的就是这块内存地址的值了。 int 是指针的类型,刚才说过,指针变量占用的内存空间永远是32位,相当于一个int的大小。但是,指针是有类型的,它不是用来给指针变量本身分配内存,它是用来做什么的呢? 它是 用来寻址 的。看下面的代码。 (int*)pointer = malloc(sizeof(int) * 5); printf("%d",*(pointer + 1)); 这段代码中先申请5个int大小的内存空间,把这段内存空间的首地址付给pointer。然后打印出第2个int元素的值。 如果这里的pointer是char类型的,那么pointer+1指向的不是第2个Int,而是第一个int的中间部分。也就是说对于不同变量类型的指针来说,+1跨过的内存单元数是不同的。指针的类新也可以是自定义的结构的类型。 与java不同,C语言的函数是不允许以引用的方式传值的,也就是说对于所有的C函数,传入的参数都是一个复制的值。 比如这样一个交换数值的函数 void switch(int a ,int b) { int c =a; a = b; b = c; } 这个函数调用后实际上并没有交换两个参数的值,因为是传值的,而非传地址(引用)的。 那么我们如何实现累类似引用传值的功能呢? 答案是,用指针。 void switch(int* a ,int* b) { int c =*a; *a = *b; *b = c; } 从本质上说指针也是被复制后传到函数体内的。 我们以上面这个函数为例分析一下 函数一 : 当调用 switch(intA,intB)时 假设 : intA 地址 0X0000000A 值 1 intB 地址 0X0000000B 值 2 经过复制之后实际上传入函数的是另外两个。 a 地址 0X000000AA 值 1 b 地址 0X000000BB 值 2 当函数执行后,intA,intB的值没变,他们从头到尾都没进入函数,进入的是他们的副本。变的是a , b的值(如下),但是函数执行结束后a , b都已经被丢弃了。没有达到预期目的。 a 地址 0X000000AA 值 2 b 地址 0X000000BB 值 1 函数二 : 当调用 switch(*intA,*intB)时 假设 : intA 地址 0X0000000A 值 0X00000A0A intB 地址 0X0000000B 值 0X00000B0B 地址 0X00000A0A 值 1 地址 0X00000B0B 值 2 当函数执行时,先复制参数,结果如下 a 地址 0X000000AA 值 0X00000A0A b 地址 0X000000BB 值 0X00000B0B 而地址0X00000A0A 和 0X00000B0A 的值没有变化 传入函数后用的都是指针变量的值,也就是说改变的是0X00000A0A 和0X00000B0B的值,而指针intA和intB的值没有变化,始终指向0X00000A0A 和0X00000B0B 所以最终达到交换数值的预期效果。
|