2017-01-15 29 views
1

我試圖將一個字符數組'p'傳遞給函數'func',並將其複製到函數內的另一個參數'arg'。但是,數組並沒有被複制,儘管我可以在'func'中修改'p'的內容並且能夠驗證主函數中的更改,'res'不會被複制從'p'。它打印空白。我不確定我犯了什麼錯誤。C - 將數組作爲函數參數返回

#include <stdio.h> 
#include <stdlib.h> 

void func(char *c, int size, char *res) 
{ 
     int i; 
     printf("Printing c in func...\n"); 
     for(i=0;i<size;i++) { 
       printf("%c",c[i]); 
     } 
     printf("\n"); 
     c[2] = 'j'; 
     res = c; 
} 

int main(void) 
{ 
     char c[5]={'h','e','l','l','o'}; 
     char *p,*arg; 
     int i, size = 5; 
     p=c; 
     arg = (char*)malloc(size); 
     func(p,size,arg); 
     printf("Printing p in main...\n"); 
     for(i=0;i<size;i++) { 
       printf("%c",p[i]); 
     } 
     printf("\n"); 
     printf("Printing arg in main...\n"); 
     for(i=0;i<size;i++) { 
       printf("%c",arg[i]); 
     } 
     printf("\n"); 

     return 0; 
} 

輸出:

Printing c in func... 
hello 
Printing p in main... 
hejlo 
Printing arg in main... 

回答

2

在C中,參數的函數由值來傳遞。函數執行到達結束後,位置resc不存在。請注意,您所做的更改與指針本身有關,而不是位置指針指向的位置。因此對res的任何更改將不會對main可見。

要使更改對main可見,您需要將arg的地址傳遞給函數func

func簽名應該是

void func(char *c, int size, char **res) ; 

main呼籲應

func(p, size, &arg); 

分配res = c;也更改爲*res = c;在功能func

在這種情況下,您正在傳遞指針arg的地址,並且更改的位置是res指向的位置。 res指向的地址爲reg,因此對res指向的地址的任何更改都將持續存在,並可見於main

現在看看它是如何工作的。最初,當你打電話給你的功能func所建議的修改後:

 +-----------+    (0x300 is a random memory location) 
     |   | 
arg | 0x300 | <---------+ 
     |   |   | 
     +-----------+   | 
     0x100     | 
           | 
           | 
     +-----------+   | 
     |   |   | 
res | 0x100 +-----------+ 
     |   | 
     +-----------+ 
     0x200 

當您指定c*res(的reg別名),*res將使reg以指向c點。假設字符串hello存儲在0x500然後*res = c會讓reg指向0x500

              Array c (in main) 
     +-----------+         +-----+-----+-----+-----+-----+------+ 
     |   +--------------------------------->+ 'h' | 'e' | 'j' | 'l' | 'o' | '\0' | 
arg | 0x500 | <---------+      +-----+-----+-----+-----+-----+-------          
     |   |   |      0x500 .... 
     +-----------+   | 
     0x100     | 
           | *res = c 
           | 
     +-----------+   | 
     |   |   | 
res | 0x100 +-----------+ 
     |   | 
     +-----------+ 
     0x200 
+0

感謝。那麼,即使函數退出後,數組「p」的更改如何仍然存在? – Gomu

+0

@Gomu;編輯答案。 – haccks

1

在C指針AR按值epassed到的功能,所以在你的函數:

void func(char *c, int size, char *res) 

資源是一個完全與傳遞給它的指針不同的對象

func(p, size, arg); 

它是不同於arg,但它指向(指向它傳遞給此函數的時刻指向的arg的相同位置)。

因此分配

res = c; 

狂內部的函數僅改變局部指針(函數內部的一個)。如果你不是做

*res = *c; 

那麼指向的內存就會發生變化,爲指向的內存由原來的指針相同作爲一個尖銳的,這將是從功能的外部可見通過res。這也是爲什麼寫'j'c[2]改變原來的數組:

c[2] = 'j'; /* note: this is same as *(c + 2) = 'j'; and this is why it works - you 
       are using memory pointed to by pointer */ 

如果需要改變自己,你需要的地址傳遞給指針代替指針:

void func(char *c, int size, char **res) 
+0

但是,即使在函數退出後,數組「p」的更改如何仍然存在? – Gomu

+0

這是因爲c [2] ='j'將'j'寫入由c + 2指向的內存。 – 4pie0