二級指標引數傳遞問題
*********************************************************************************
程式1: |
*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();
}