1. 程式人生 > >二級指標引數傳遞問題

二級指標引數傳遞問題

char g_csName[5][126]; for (int i=0; i<5; i++) {     strcpy(g_csName[i], "123"); } void Fun(char** csName){} 請問下,我現在要把csName作為引數傳遞到Fun()函式中, 該如何傳遞我呼叫了Fun( (char**)g_csName ) 但是除錯進入的時候,沒有值。 傳遞二維陣列的陣列名不能使用二級指標來接收他們型別不皮配的應使用陣列指標, 即char (*p)[126] 指標型別解釋 int **p;   //首先p和*結合,表時變數p是一個指標,然後再與*結合,表明這個指標指向的是一處指標的地址。 int (*p)[126];   // 首先p和*結合,表時變數p是一個指標,然後再與[]結合,表明這個指標指向的是一個帶有126個元素的一維陣列的地址。
*********************************************************************************

程式1: 
void myMalloc(char *s) //我想在函式中分配記憶體,再返回 

     s=(char *) malloc(100); 

void main() 

     char *p=NULL; 
     myMalloc(p);    //這裡的p實際還是NULL,p的值沒有改變,為什麼? 
     if(p) free(p); 

程式2:void myMalloc(char **s) 

     *s=(char *) malloc(100); 

void main() 

     char *p=NULL; 
     myMalloc(&p);    //這裡的p可以得到正確的值了 
     if(p) free(p); 

程式3: 
#include<stdio.h> 
void fun(int *p) 

       int b=100; 
       p=&b; 

main() 

       int a=10; 
       int *q; 
       q=&a; 
       printf("%d/n",*q); 
       fun(q); 
       printf("%d/n",*q); 
       return 0; 

結果為 
10 
10 
程式4: 
#include<stdio.h> 
void fun(int *p) 

       *p=100; 

main() 

       int a=10; 
       int *q; 
       q=&a; 
       printf("%d/n",*q); 
       fun(q); 
       printf("%d/n",*q); 
       return 0; 

結果為 
10 
100 
為什麼? 
--------------------------------------------------------------- 
1.被分配記憶體的是行參s,p沒有分配記憶體 
2.被分配記憶體的是行參s指向的指標p,所以分配了記憶體 
--------------------------------------------------------------- 
不是指標沒明白,是函式呼叫的問題!看看這段: 
7.4指標引數是如何傳遞記憶體的? 
           如果函式的引數是一個指標,不要指望用該指標去申請動態記憶體。示例7-4-1中,Test函式的語句GetMemory(str, 200)並沒有使str獲得期望的記憶體,str依舊是NULL,為什麼? 
void GetMemory(char *p, int num) 

           p = (char *)malloc(sizeof(char) * num); 

void Test(void) 

           char *str = NULL; 
           GetMemory(str, 100);            // str 仍然為 NULL              
           strcpy(str, "hello");            // 執行錯誤 

示例7-4-1 試圖用指標引數申請動態記憶體 
毛 病出在函式GetMemory中。編譯器總是要為函式的每個引數製作臨時副本,指標引數p的副本是 _p,編譯器使 _p = p。如果函式體內的程式修改了_p的內容,就導致引數p的內容作相應的修改。這就是指標可以用作輸出引數的原因。在本例中,_p申請了新的記憶體,只是把 _p所指的記憶體地址改變了,但是p絲毫未變。所以函式GetMemory並不能輸出任何東西。事實上,每執行一次GetMemory就會洩露一塊記憶體,因 為沒有用free釋放記憶體。 
如果非得要用指標引數去申請記憶體,那麼應該改用“指向指標的指標”,見示例7-4-2。 
void GetMemory2(char **p, int num) 

           *p = (char *)malloc(sizeof(char) * num); 

void Test2(void) 

           char *str = NULL; 
           GetMemory2(&str, 100);            // 注意引數是 &str,而不是str 
           strcpy(str, "hello");              
           cout<< str << endl; 
           free(str);              

示例7-4-2用指向指標的指標申請動態記憶體 
由於“指向指標的指標”這個概念不容易理解,我們可以用函式返回值來傳遞動態記憶體。這種方法更加簡單,見示例7-4-3。 
char *GetMemory3(int num) 

           char *p = (char *)malloc(sizeof(char) * num); 
           return p; 

void Test3(void) 

           char *str = NULL; 
           str = GetMemory3(100);              
           strcpy(str, "hello"); 
           cout<< str << endl; 
           free(str);              

示例7-4-3 用函式返回值來傳遞動態記憶體 
用函式返回值來傳遞動態記憶體這種方法雖然好用,但是常常有人把return語句用錯了。這裡強調不要用return語句返回指向“棧記憶體”的指標,因為該記憶體在函式結束時自動消亡,見示例7-4-4。 
char *GetString(void) 

           char p[] = "hello world"; 
           return p;            // 編譯器將提出警告 

void Test4(void) 

char *str = NULL; 
str = GetString();            // str 的內容是垃圾 
cout<< str << endl; 

示例7-4-4 return語句返回指向“棧記憶體”的指標 
用偵錯程式逐步跟蹤Test4,發現執行str = GetString語句後str不再是NULL指標,但是str的內容不是“hello world”而是垃圾。 
如果把示例7-4-4改寫成示例7-4-5,會怎麼樣? 
char *GetString2(void) 

           char *p = "hello world"; 
           return p; 

void Test5(void) 

           char *str = NULL; 
           str = GetString2(); 
           cout<< str << endl; 

示例7-4-5 return語句返回常量字串 
函 數Test5執行雖然不會出錯,但是函式GetString2的設計概念卻是錯誤的。因為GetString2內的“hello world”是常量字串,位於靜態儲存區,它在程式生命期內恆定不變。無論什麼時候呼叫GetString2,它返回的始終是同一個“只讀”的記憶體 塊。 
--------------------------------------------------------------- 
看看林銳的《高質量的C/C++程式設計》呀,上面講得很清楚的 
--------------------------------------------------------------- 
對於1和2: 
如果傳入的是一級指標S的話, 
那麼函式中將使用的是S的拷貝, 
要改變S的值,只能傳入指向S的指標,即二級指標 
--------------------------------------------------------------- 
程式1: 
void myMalloc(char *s) //我想在函式中分配記憶體,再返回 

     s=(char *) malloc(100); // s是值參, 函式返回後就回復傳遞前的數值,無法帶回分配的結果 

這個和呼叫 void func (int i) {i=1;}; 一樣,退出函式體,i指復原的 
程式2:void myMalloc(char **s) 
{

*s=(char *) malloc(100); // 這個是可以的 

等價於 
void int func(int * pI) {*pI=1;} pI指標不變,指標指向的資料內容是變化的 
值參本身不變,但是值參指向的記憶體的內容發生了變化。 
程式3: 
void fun(int *p) 

       int b=100; 
       p=&b;                  // 等同於第一個問題, b的地址並沒有被返回 

程式4: 
void fun(int *p) 

       *p=100;    // okay 

--------------------------------------------------------------- 
其實樓主的問題和指標沒有多大關係,就是行參和值參的問題 
函式呼叫的時候,值參傳遞的是數值,是不會返回的 
這個數值,在函式體內部相當於一個變數,是可以改變,但是這個改變是無法帶出函式體外部的 
--------------------------------------------------------------- 
程式1: 
void myMalloc(char *s) //我想在函式中分配記憶體,再返回 

     s=(char *) malloc(100);//傳過來的是P所指的地址,並不是P的地址,所以改變S不會改變P 

void main() 

     char *p=NULL; 
     myMalloc(p);    //這裡的p實際還是NULL,p的值沒有改變,為什麼? 
     if(p) free(p); 

程式2:void myMalloc(char **s) 

     *s=(char *) malloc(100);//S指向的是P的地址,所以改變了P所指的記憶體單元. 

void main() 

     char *p=NULL; 
     myMalloc(&p);    //這裡的p可以得到正確的值了 
     if(p) free(p); 

程式3: 
#include<stdio.h> 
void fun(int *p) 

       int b=100; 
       p=&b; 

main() 

       int a=10; 
       int *q; 
       q=&a; 
       printf("%d/n",*q); 
       fun(q);////道理同第一個程式. 
       printf("%d/n",*q); 
       return 0; 

結果為 
10 
10 
程式4: 
#include<stdio.h> 
void fun(int *p) 

       *p=100;//引數P和實參P所指的記憶體單元是相同的.所以改變了引數P的記憶體單元內容,就改變了實參 
                     //的記憶體單元內容 

main() 

       int a=10; 
       int *q; 
       q=&a; 
       printf("%d/n",*q); 
       fun(q); 
       printf("%d/n",*q); 
       return 0; 

結果為 
10 
100 
為什麼? 
--------------------------------------------------------------- 
void main() 

     char *p=NULL; 
     myMalloc(p);    //這裡的p實際還是NULL,p的值沒有改變,為什麼? 
     if(p) free(p); 

void myMalloc(char *s) //我想在函式中分配記憶體,再返回 

     s=(char *) malloc(100); 

myMalloc(p)的執行過程: 
分配一個臨時變數char *s,s的值等於p,也就是NULL,但是s佔用的是與p不同的記憶體空間。此後函式的執行與p一點關係都沒有了!只是用p的值來初始化s。 
然後s=(char *) malloc(100),把s的值賦成malloc的地址,對p的值沒有任何影響。p的值還是NULL。 
注意指標變數只是一個特殊的變數,實際上它存的是整數值,但是它是記憶體中的某個地址。通過它可以訪問這個地址。 
程式2:void myMalloc(char **s) 

     *s=(char *) malloc(100); 

void main() 

     char *p=NULL; 
     myMalloc(&p);    //這裡的p可以得到正確的值了 
     if(p) free(p); 

程式2是正確的,為什麼呢?看一個執行過程就知道了: 
myMalloc(&p);將p的地址傳入函式,假設儲存p變數的地址是0x5555,則0x5555這個地址存的是指標變數p的值,也就是Ox5555指向p。 
呼叫的時候同樣分配一個臨時變數char **s,此時s 的值是&p的值也就是0x5555,但是s所佔的空間是另外的空間,只不過它所指向的值是一個地址:Ox5555。 
*s=(char *) malloc(100);這一句話的意思是將s所指向的值,也就是0x5555這個位置上的變數的值賦為(char *) malloc(100),而0x5555這個位置上存的是恰好是指標變數p,這樣p的值就變成了(char *) malloc(100)的值。即p的值是新分配的這塊記憶體的起始地址。 
這個問題理解起來有點繞,關鍵是理解變數作函式形參呼叫的 時候都是要分配一個副本,不管是傳值還是傳址。傳入後就和形參沒有關係了,它不會改變形參的值。myMalloc(p)不會改變p的值,p的值當然是 NULL,它只能改變p所指向的記憶體地址的值。但是myMalloc(&p)為什麼就可以了,它不會改變(&p)的值也不可能改變,但是 它可以改變(&p)所指向記憶體地址的值,即p的值。 
--------------------------------------------------------------- 
你要弄清楚的是指標變數和指標所指的變數(可能是一片記憶體)。 
指標變數和普通變數一樣儲存的,

//////////////////////////////////////////////////////////////////


1.如果是函式內進行記憶體申請,很簡單,標準用法就可以了:
test()
{
 int *array;
 
 array=(int *)malloc(sizeof(int)*10);//申請10*4 bytes,即10個單位的int記憶體單元
}
注意,malloc使用簡單,但是注意引數和返回值,引數是申請記憶體的位元組數,多位元組的型別如int,short,float等需要乘上型別位元組數,返回值是沒有定義型別的指標,使用時需要自己指定。
2.使用一級指標實現記憶體申請,通過函式返回值帶出malloc的地址:
char *my_malloc(int m)
{
 char *p;
 p=malloc(m);
 return p;
}
test()
{
 char * buff=NULL;  //指標如果在函式內沒有賦值,注意開始賦值為NULL
 buff=my_malloc(10);
 printf("buff adress is %x/n",buff);
 free(buff);  
}
3.使用二級指標實現記憶體申請,通過指標值傳遞:
void my_malloc1(char **p1)
{
 *p1=(char *)malloc(100);
}
test()
{
 char *buffer=NULL;
 
 my_malloc1(&buffer);
 printf("buffer adress is %x/n",buffer);
 free(buffer);
}
小結:一級指標和二級指標在做形參時的不同:指標用作形參,改變指標地址則值不能傳回,改變指標內容而地址不變則值可以傳回。(特殊情況:改變指標地址採用返回值也可以傳回地址)
對於一級指標,做形參時傳入地址,如果函式只改變該指標內容,OK,該指標可以正常返回,如果函式改變了指標地址,除非返回該指標,否則該指標不能正常返回,函式內對指標的操作將無效。
對於二級指標,做形參時傳入地址(注意此時傳入的是二級指標的地址),如果改變該二級指標地址(**p),對該指標的操作也將無效,但是改變二級指標的內容(例如*p),則該二級指標可以正常返回。
總之,指標使用最關鍵的是弄清地址和內容,指標做形參時只有改變其內容時才能正常返回。
 
4.程式設計例項:
/*
date:20100823
file name:my_pointer.c
description:指標作為形參的值傳遞分析
result:
1.指標作為形參時,如果只需要改變指標指向的值,可以使用一級指標,如果需要改變指標本身的地址
,則需要使用二級指標,相當於改變的是一級指標指向的值。
2.指標作為形參時,指標指向的內容變化是可以帶回的,指標地址的變化是不可帶回的,即指標作為參
數,其地址不可改變,否則形參就無法傳回實參的值。
*/
/*********************************************************************************/
//指標作為形參,指標指向的內容改變,函式返回時這種變化是可以帶回的
void change(int *p)
{
 *p+=5; 
}
test1()  
{
 int a=1;
 
 change(&a);
 
 printf("After change a is %d/n",a);  //結果為6
}
/*********************************************************************************/
//指標作為形參,指標本身的地址改變,函式返回時這種變化將無效
void my_malloc(char *pp,int num)   
{
 pp=(char *)malloc(num); 
}
test2()       
{
 char *buf=NULL;
 
 my_malloc(buf,100);
 
 printf("After my_malloc buf adress is %x/n",buf); //函式返回後,buf的地址依然為NULL 
 strcpy(buf,"hello");         //這裡會出錯,執行出現段錯誤,程式直接退出了,下面的輸
出也沒有了
 puts(buf);
}
main()
{
 test1();
 //test2();
}

相關推薦

二級指標引數傳遞問題

char g_csName[5][126]; for (int i=0; i<5; i++) {     strcpy(g_csName[i], "123"); } void Fun(char** csName){} 請問下,我現在要把csName作為引數傳遞到Fun

指標引數傳遞實質及二級指標使用

水平有限,如有錯誤,歡迎指正,謝謝。 先看兩個程式: 耐心仔細看,應該能理解。 1: void test(char *p) {        printf("[test1][p]:%p.\n",p);        printf("[test2][p]:%s.\n",p);

二維陣列和二級指標傳遞問題

再次看這篇文章,感覺說的好多都是廢話,在文章最前面補充一句話: “[]的優先順序高於*”,大家可以帶著這句話看下面的~~~ ======================== 再一次的見證了自己的基礎不牢靠。。。幸好發現得早,看見網上說,華為的一個面試題就考了這個方面的

二級指標傳遞時注意地方

/*******************二級指標的傳遞************************/ #include <stdio.h> #include <string.

C++指標引數傳遞記憶體 及 在函式中用指標new的一個空間

通過幾個例子說明C++指標引數傳遞記憶體的問題 例子一: void GetMemory(char* p, int num) { p = (char*)malloc( sizeof(char) * num ); return; } int main(void)

二叉樹演算法引發的指標引數傳遞和引用的思考

最近想熟悉一下基本的資料結構和演算法,於是寫了一個二叉樹程式,功能很簡單,只有二叉樹的建立和遍歷。在這個過程中,卻發現了一些平時沒有注意到的細節問題,寫出來作為總結和大家分享。 待討論和遇到的細節問題如下: (1)常見的定式思維:指標作為引數傳遞,是否就不需要再賦值

【轉】C++函式引數傳遞中的一級指標二級指標【【**】】

主要內容: 1、一級指標和二級指標 2、函式指標傳遞的例子 3、什麼時候需要傳遞二級指標? 4、二級指標在連結串列中的使用 1、一級指標和二級指標 一級指標:即我們一般說的指標,就是記憶體地址; 二級指標:指向指標的指標,就是

一級指標二級指標的函式引數傳遞

/*初始化單鏈表*/ /********************************************************   *  函式名:int InitList(LinkList *L)   *  函式功能: 初始化單鏈表   *  輸入引數:LinkList *L   *  輸出引數:i

C++ 有關指標作為函式引數的問題,自定義記憶體分配函式傳遞二級指標的問題

如題所示,我們主要討論在自定義的記憶體分配函式中通常見到的程式碼如下所示: ``` void Create(A** addr); ``` 其中傳遞的引數是二級指標。為什麼? 我們先看一下完整的動態記憶體分配函式的簡單例子: ``` struct A { int a = 0; int b = 0

連結串列頭節點問題(指標作為引數傳遞不能為NULL)

真是腦殘,以前沒有注意過這個問題,今天噁心了我好一會。做個記錄,以後不要再犯。  這樣在main函式裡面定義一個指標變數然後傳進函式裡面在申請空間的做法是錯誤的。 void creat(node* head) { if(head==NULL){ head=(node*)mal

day02 Go 指標引數傳遞

1、什麼是指標 一個指標變數指向了一個值的記憶體地址。 類似於變數和常量,在使用指標前你需要宣告指標。指標宣告格式如下: var var_name *var-type var-type 為指標型別,var_name 為指標變數名,* 號用於指定變數是作為一個指標。以下是有效的指標宣告:

c指標作為引數傳遞以及指標指標

#include "stdio.h" void pointer(int *p) { int a = 11; printf("\n\nEnter function"); printf("\nthe p is point to %p , addr is %X, *p is %d",p ,

cgo傳遞golang slice, 以及使用二級指標獲取值

背景: 在golang中呼叫c函式時,會通過slice傳遞一組數;以及想通過二級指標引用獲取c中的變數值,這樣就不用再c中單獨定義變數,有可能還有手動釋放變數。 示例 package main /* #include <stdio.h> int loop(int**

C語言函式傳遞指標引數

  #include <stdio.h> void swap(int *a,int *b) { printf("address in swap():%p %p\n",a,b); int temp=*a; *a=*b; *b=temp; } i

C語言指標作為函式引數傳遞學習(一)

1. 一維指標做函式引數 傳入的指標為NULL 比如下面的例子,很多人都會理解錯: #include <stdio.h> void test(char *string) { string = "hello world"; } int main() { cha

c++之指標作為函式引數傳遞的問題

轉自:http://blog.csdn.net/fjb2080/article/details/5623427   原創文章,轉載請註明出處,謝謝! 作者:清林,部落格名:飛空靜渡   部落格地址:http://blog.csdn.net/fjb2080 &n

陣列和指標做函式引數傳遞

#include<iostream> using namespace std; void callByValue(int arr[], int n) { printf("\ncallByValue:"); for (int i = 0;i < 10;

指標作為函式引數傳遞 (轉載)

這幾天在學習C過程中,在使用指標作為函式引數傳遞的時候出現了問題,根本不知道從何得解:原始碼如下:    createNode(BinNode *tree,char *p)    {        tree = (BinNode *) malloc(sizeof(BinNo

C語言陣列與指標作為傳遞引數的使用

       學習筆記中的內容多少會有一點文不對題,因為C語言中陣列無法作為函式的一個傳遞引數。而陣列名在作為函式傳遞引數使用的時候實際上也被轉換成了一個指標。 編寫如下程式碼; #include"s

二維指標、二維陣列、指向陣列的指標 函式引數傳遞

 前兩天寫個程式,傳引數的時候想傳個二維陣列進去,結果悲劇了,函式寫成 Fun (int **p){},原來沒有這麼寫過,以為這麼寫也是對的,結果錯了,查了些資料, 做個總結。 Fun (int **p){} 這裡面的int **p //這裡的p不是二維陣列的指標,而是指向指標的指標,即二級指標。