2014-03-30 46 views
3

我用字符串中的數位以下功能:爲什麼向前移動指針不會影響外部函數?

int countSpace(char *str) { 
     int nSpaces = 0; 
     while (*(str) != '\0') { 
       if (*(str) == ' ') { 
         nSpaces++; 
       } 
       str++; 
     } 
     return nSpaces; 
} 

我用這個函數是這樣的:

char a[]="Hello "; 
printf("%d", countSpace(a)); 

我的問題是,當我這樣做:printf("%s", a);,呼籲countSpace後,爲什麼a沒有指向最後?我的意思是,我已經增加了countSpace函數內的指針,但外部似乎仍然指向最初。這是爲什麼?

我知道我在countSpace函數內的* str所做的更改會影響外部,所以如果例如我這樣做:str[0] = 'p',在函數的外部,a的值將是pola。所以,我不明白爲什麼指針仍然指向一開始,即使在我已經使它前進的函數中。

+0

由於串它只是複製的char數組。將指針傳遞給指針,它將起作用。 –

+0

http://stackoverflow.com/questions/4426474/is-passing-pointer-argument-pass-by-value-in-c – DCoder

回答

4

因爲C按值傳遞參數

int countSpace(char *str) 
         ^^ 
      This pointer is a copy of the pointer you pass in. 

最初,你str變量指向同一件事的指針,你 傳遞給你的函數,但裏面countSpace()你只是incremeting的本地副本那個指針。

+0

但是,如果它是一個副本如何進入該函數內部我可以做str [2] ='l',那會改變外面的值? – StarTrek18

+1

@ StarTrek18指針是一個副本,但它指向內存中的相同地址,因此如果更改數據,則在函數返回後仍會保留更改,即使指針未更改。 – dutt

+1

@ StarTrek18 - **指針**按值複製。內存區域,它指向,根本不復制。將指針看作是一個整數值(它指向的對象的地址)。該整數按值傳遞。 – Dirk

1

C是通過按值,所以當你通過指針countSpaces它使指針的值的副本(請注意,只是指針它所指向)。就像其他任何本地值一樣:在函數內部對其進行的任何更改都不會反映到外部。

函數內部的指針指向的內容的任何更改都會在函數外部看到。

例如:我們採取的a的地址,將其存儲在指針p並打印,作爲一個指針(看到它保持存儲器地址):

char * p = a; 
printf(" p = %p\n", p); // This will not print the string, but the address where it starts 

並傳遞到countSpaces(這相當於通過acountSpaces):

​​

現在內,打印str作爲指針

printf(" str: %p\n", str); 

你會看到,這兩個值是相同的,這是有道理的,因爲它被複制到countSpaces。但是,如果您打印的地址pcountSpaces之外)和地址str(內部)。你會看到,他們是不同的:

printf("&str: %p\n", &str); 

printf("&p: %p\n", &p); 

因此,countSpaces可以改變什麼strp(和a,而不是指針本身:他們被複制到新的變量。

0

str是傳遞給函數的參數列表的指針的副本。它與int參數沒有區別。因此,a不變。

+0

我不明白,因爲如果在函數內我做''str [3] ='P' ;',我打印外部值,它實際上已經改變了它的值。 – StarTrek18

+0

因爲'ptr'是'a'的副本。所以,他們是指向相同內存位置的兩個指針。如果您更改該內存位置的內容,則會從兩個指針訪問更改。 – SJuan76

0

str是一個指向字符串的指針,並通過值傳遞給該函數。

當您在函數內部更改str時,函數外部傳遞的原始變量不會更改。

當然作爲str是一個指針,它允許你改變它指向的char

如果你想改變您的函數內str你有一個指針的指針傳遞給str,換句話說就是一個指向您的字符串(第一個字符)。

的代碼變爲:

int countSpace(char **str) { 
     int nSpaces = 0; 
     while (**(str) != '\0') { 
       if (**(str) == ' ') { 
         nSpaces++; 
       } 
       *str++; 
     } 
     return nSpaces; 
} 

使用此功能是這樣的:

char a[]="Hello "; 
printf("%d", countSpace(&a)); 
1

變量a不被功能改變。

瞭解內存中的變量和值在哪裏有助於理解指針發生了什麼。以及稍後幫助調試。

做一個和str的%p printf,你會看到他們指向的內存地址。

printf("a var %p", &a); 
printf("a content %p", a); 
printf("str var %p", &str); 
printf("str content %p", str); 

例如,事情在內存中假設寶寶2字節int和ptrs。

# c compiler/linker will put string values in global memory 

#Addr #Value 
#0020 Hello \0 
#0027 %d\0 
#0030 . . 

堆棧內存。變種a是在棧MEM(在主函數的棧承擔)(實際上編譯器可以放置瓦爾到寄存器中,但相同的結果產生)

#stack-main a is a char ptr. 
#&a=0100, value of a=0020 
#Addr #Value 
#0100 0020 

#when countSpaces is just called 
#code return addr pushed to stack 
#Addr #Value 
#0102 0222 
#space on stack for return of int 
#0104 0000 
#value of a put on stack (this is str) 
#0106 0020 
#local vars of countSpaces 
# int nSpaces 
#0107 0000 

後countSpaces返回堆棧的樣子:

#&a=0100, value of a=0020 
#Addr #Value 
#0100 0020 

#Addr #Value 
#code return addr 
#0102 0222 
#space on stack for return of int 
#0104 0001 
#value of a put on stack (this is str) 
#0106 0026 
#local vars of countSpaces 
# int nSpaces 
#0107 0001 
相關問題