2016-01-15 160 views
3

我一直在試圖從一個函數用下面的代碼和它接受一個結構,並返回一個指向它的指針的功能的指針返回到一結構:返回一個指針從一個函數構造

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

struct mystruct 
{ 
    int id; 
    char name[10]; 
}; 


//this is the function 
struct mystruct *return_pointer(struct mystruct a) 
{ 
    struct mystruct *ptr; 
    ptr = &a; 
    return ptr; 
} 

int main() 
{ 
    struct mystruct tag, *p; 
    tag.id = 12; 
    strcpy(tag.name,"abcd"); 

    printf("Values are: %d\t%s",tag.id,tag.name); 
    p=return_pointer(tag); 

    printf("\nValues through pointer: %d\t%s", p->id, p->name); 
    return 0; 
} 

但是當我嘗試使用返回的指針訪問結構的值時,它無法正常工作。它只顯示'id'而不是'name'。 這裏可能存在什麼問題? 我已經在讀一本書,說在功能上的身體利用這一點:

ptr = (struct mystruct *)malloc(sizeof(struct mystruct)); 
ptr-> id = a.id; 
strcpy(p->name,a.name); 
//struct 'a' is argument to function 

return ptr; 

如果這是正確的解決方案,那麼爲什麼這樣呢?

+4

'return_pointer'函數的用途是什麼?這似乎毫無意義。 –

+0

@MichaelWalz不要故意! – Lincoln

回答

7

因爲您正在返回a,它是您傳遞的副本。 中的參數按值傳遞,因此a是在不同位置分配的tag的副本,該位置是該函數的堆棧框架,並且在函數返回時將被銷燬。

因此,在打印的時候,您正在打印解除分配的struct,這是未定義的行爲。如果你希望你的代碼,不管出於什麼原因工作試試這個

struct mystruct * 
return_pointer(struct mystruct *a) 
{ 
    return a; 
} 

main()改變它

p = return_pointer(&tag); 
//    ^Pass the address of tag and return it 
//     the same as 
//      
//         p = &tag; 
// 
//     which is why they say it's pointless in 
//     the comments 

當您使用malloc()你在堆上分配struct,該數據將是有效的地方可以使用,直到用free()手動銷燬它,free()函數只會釋放內存,它不會在意將來會做什麼,它只是將它回饋給它。

此外,總是檢查malloc()的返回值。


只要有保持所述存儲器的由malloc()淵源返回的地址的指針。當您決定不再需要struct時,這正是您必須傳遞給free()的地址。

+1

但實際上,只是'p = &tag;'就可以了。 – Caleb

+0

@Caleb,我知道請看最後的答案。 –

+0

對不起,錯過了你的評論,但也許如果我們都說它10或12次消息將通過。 ;-) – Caleb

4

你應該這樣做,而不是:

p = &tag; 

指向相同的結構tag。不這樣做:

p = return_pointer(tag); 

因爲當你通過tag,按值傳遞它,因此它會創建一個副本(在功能return_pointer稱爲a),您taga(具體而言,那些地址(即&tag&a)是不同的 - 參見Caleb先生的評論)在函數中是不一樣的。

+1

具體而言,'&tag'和'&a'將具有不同的值。 – Caleb

+1

@Caleb啊是的,你是對的。這更準確。 – Ian

2

函數參數是函數的局部變量。在功能完成後它們被銷燬。

你想要做的是通過引用傳遞一個結構並返回對它的引用。在這種情況下,功能將類似於

//this is the function 
struct mystruct * return_pointer(struct mystruct *ptr) 
{ 
    return ptr; 
} 

,並呼籲像

p = return_pointer(&tag); 

雖然有這樣的功能沒有很大的用處。儘管如此,通常它可以改變傳遞對象的一些數據成員。

+0

_沒有這種功能的巨大作用_...我可以想到一些,包括一個應用程序調用到一個庫,爲一個_ [PSP](http://ieeexplore.ieee.org/xpl/login。 jsp?tp =&arnumber = 4554519&url = http%3A%2F%2Fieeexplore.ieee.org%2Fxpls%2Fabs_all.jsp%3Farnumber%3D4554519)_網絡,其中一個簡單的調用庫可以將信息傳遞給庫,並通過'struct *'。儘管如此,答案很好。 – ryyker

0

我是中國的代碼初學者,你的代碼的錯誤在於局部變量(ptr是一個指針)的域只在函數中有效,但是當你將它返回給你的全局主函數時,它指出已經釋放的記憶。所以它變成了一個錯誤。我的快樂回答你!