关于“指针的指针”的认识(值传递、指针传递区分)
【摘要】對于C語言的參數(shù)傳遞通常都是值傳遞,當傳傳遞一個指針給函數(shù)的時,其實質(zhì)上還是值傳遞。我們可以看以下常見的面試題:
#include <stdio.h> #include <stdlib.h> #include <string.h>void function1(int *v) {v = (int *)malloc(sizeof(int));*v = 100; }void main() {int *v = NULL;function1(v);printf("%d\n",*v); }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
分析:指針其實本質(zhì)就是一個變量,存放的是地址,不過也是一個值罷了,只不過特殊一點。本段函數(shù)的被調(diào)函數(shù)就把這個值(也就是地址)拷貝了下來。被調(diào)函數(shù)執(zhí)行了 v = (int *)malloc(sizeof(int)); 之后,這樣一條語句主動申請一塊內(nèi)存,并把這塊內(nèi)存的地址返回給v ,悄然把地址修改啦。這時主函數(shù)和被調(diào)函數(shù)中的指針指向的東西沒有半毛關系了,主函數(shù)中v還是NULL,所以……
1、指針傳遞與值傳遞
我們再來看以一個交換2個數(shù)的值的函數(shù)調(diào)用的代碼:
void swap ( int *a, int *b ){int c;c = *a;*a = *b;*b = c; } int main(int argc, char **argv){int a,b;a = 16;b = 32;swap( &a, &b);return ( a - b ); }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
分析:能夠正常交換a,b的值,被調(diào)函數(shù)操作的*a變量解引用一下,其實它的地址和主調(diào)函數(shù)a是一樣的。因此它們操作是在同一塊內(nèi)存區(qū)域,可以實現(xiàn)數(shù)值的交換。
下面貼出一個錯誤的代碼:
void swap ( int *a, int *b ){int *temp;temp = NULL;temp = a;a = b;b = temp; } int main ( int argc, char **argv ){int a,b;a = 16;b = 32;swap(&a, &b);return ( a - b ); }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
分析:這種方式按照理論上來說,是想通過調(diào)用swap函數(shù),在swap函數(shù)內(nèi)部,實現(xiàn)將交換&a,&b,即交換a和b的地址來達到目的。但是被調(diào)函數(shù)只是對a,b的地址進行拷貝,簡單一點說其實就相當于值傳遞,即使被調(diào)函數(shù)再一次對a,b地址進行修改,對主調(diào)函數(shù)實參a,b地址是沒有任何影響的。所以根本沒有起到值交換目的的。所以上述代碼是錯誤的,無法實現(xiàn)你想要的功能。
2、指針的指針
當我們用二級指針來實現(xiàn)上述功能的時候有就可以達到效果。
#include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h>void swap ( int **a, int **b ){int *tmp = NULL;tmp = *a;*a = *b;*b = tmp; }int main ( int argc, char **argv ){ int x = 16; int y = 32; int *a = &x;int *b = &y;swap(&a, &b); printf("%d\n",*a-*b);getchar();return 0; }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
分析:這個時候,你會發(fā)現(xiàn)就能實現(xiàn)達到交換的目的。我們通過操作中間橋梁(一級指針 *a)通過交換它們的值,實現(xiàn)數(shù)值交換。
3、指針的指針常見用途
雙指針主要用在但我們想向一個A函數(shù)傳遞參數(shù)的時候,但是我們希望在A內(nèi)部對參數(shù)做任何修改都能保存起來,那么就是用雙指針吧。
舉個例子;
我們在做鏈表的時候,我們肯定希望在用一個函數(shù)creatLink(…)函數(shù)來增加鏈表節(jié)點。那么我們可以有2種方法來實現(xiàn)
第一種,用一級指針
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
分析:這樣做可以達到增加節(jié)點的目的,但是,在任何情況下,我們的操作都得死死地抓住頭指針,也即是我們增加節(jié)點后,任何對鏈表長度的修改,我們都要 鏈表頭指針返回,即 return head;所以,我們要通過這個函數(shù)最后獲得頭指針,抓住他,死死地抓住他,然后操作。
第二種方法:用雙指針,也即是二級指針。
typedef struct node{...... }list; void create(list **l){list *head;head = l;malloc...//為節(jié)點申請內(nèi)存空間......//操作 }int main(...){......list *stcreateList(st)...... //以后的任何操作,不管是刪除還是插入,我們不需要考慮,我們是否已經(jīng)return head了,不需要,我們在任何情況下,對鏈表的操作都只需要使用st來完成,因為,st就是鏈表的頭指針,不變,因為在申明st的時候,已經(jīng)為st分配 一個地址空間,它是存在的,一直存在,直到main函數(shù)結(jié)束 }- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
這里有關于指針的指針兩篇不錯的博客,推薦給大家
深入理解雙指針的兩種用法
重新認識二級指針(Pointers to Pointers)
總結(jié)
以上是生活随笔為你收集整理的关于“指针的指针”的认识(值传递、指针传递区分)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 重新认识二级指针(Pointers to
- 下一篇: python教学视频r_R Tutori