[問題] 有關於 return local variable

看板C_and_CPP作者 (gowrite)時間8年前 (2017/12/16 01:05), 8年前編輯推噓9(9015)
留言24則, 7人參與, 9年前最新討論串1/1
開發平台(Platform): (Ex: Win10, Linux, ...) GNU/Linux Ubuntu 編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出) Vim 額外使用到的函數庫(Library Used): (Ex: OpenGL, ...) n/a 問題(Question): 最近在練習資料結構, 突然想到有關於在函式中回傳區域變數的問題 不知道該怎解決,所以想問一下實際上遇到這種問題的最好的解法 餵入的資料(Input): 程式碼如下 預期的正確結果(Expected Output): 輸出沒問題 錯誤結果(Wrong Output): 沒錯誤 程式碼(Code):(請善用置底文網頁, 記得排版) /*List 結構類型*/ typedef struct node { struct node* next; char* id; }List; /*全域變數 head*/ List head = {NULL , "head"}; /*經由 get_last_node() 函式,可以回傳 linked list 的最後一個 node 的指標*/ List* get_last_node(void){ if( head.next == NULL ){ return &head; } List* current = head.next; while( current != NULL ){ if( current->next == NULL ){ return current; //我的問題就是這一行 Question,問題在下方補充 } current = current->next; } } void add_new_node(char* id){ List* last_node = get_last_node(); //....接著去 malloc 新空間 跟 新增 node 等等的動作 } void main(){ List n1 = {NULL , "n1"}; head.next = &n1; List n2 = {NULL , "n2"}; n1.next = &n2; add_new_node("another new node"); /*基本上這個程式,寫到這邊沒有發生什麼錯誤*/ /*那這邊要取得最後 node 的指標是為了更後面要實做 add_new_node() 的函式*/ } 補充說明(Supplement): 就是 current 區域變數是在 get_last_node() 函式裡面 經由一開始取得 head.next 之後,在由 while loop 來得到最後一個 node 的指標 可是因為回傳的是 current 區域變數, 回傳的時候,理論上 get_last_node() 在記憶體的空間應該已經被釋放掉了, 所以我的 main 函式可以收到正確的 current 內容,應該是運氣好記憶體內容還沒被覆蓋掉; 我看了一些 c 語言的教學,都說回傳區域變數是不好的習慣 但是在這個 case,不回傳區域變數的解決方式似乎只有兩種 第一種: 就開一個全域變數 (可是全域變數會造成命名衝突的可能) 第二種: 不回傳指標,所以後續的所有動作都在同一個函式裡面做完, current 取得指標之後,就在 get_last_node() 同一個函式裡面完成新增 node 的動作 包括 List* new_node = malloc 新空間,賦值,等等 還有把 current->next = new_node 這樣 可是這樣似乎又沒辦法遵循『一個函式只做一件事情』的好習慣 請問大家如此應該要怎辦呢?? 還是我的觀念哪裡有錯誤, 希望大家可以給我指導跟解惑, 謝謝。 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.195.54.122 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1513357506.A.7AD.html ※ 編輯: gowrite (123.195.54.122), 12/16/2017 01:08:57 ※ 編輯: gowrite (123.195.54.122), 12/16/2017 01:09:35

12/16 01:23, 8年前 , 1F
可以改成把指標傳進去給他
12/16 01:23, 1F
你好,請問你的意思是說,例如: List* last_node; get_last_node( &last_node ) 是這個意思嗎?? ※ 編輯: gowrite (123.195.54.122), 12/16/2017 01:48:12

12/16 01:55, 8年前 , 2F
不好的事情應該是「回傳指向區域變數的指標」
12/16 01:55, 2F

12/16 01:55, 8年前 , 3F
如果只是回傳一個區域變數的值那什麼事都沒有
12/16 01:55, 3F

12/16 01:56, 8年前 , 4F
因為這種事我們天天都在做
12/16 01:56, 4F

12/16 02:00, 8年前 , 5F
是這個意思
12/16 02:00, 5F

12/16 02:03, 8年前 , 6F
而且你寫法應該沒問題,他回傳的是head裡指標的值
12/16 02:03, 6F

12/16 02:21, 8年前 , 7F
原PO還沒弄懂指標真正的含義
12/16 02:21, 7F

12/16 02:56, 8年前 , 8F
你的current是指向heap的指標,ok的
12/16 02:56, 8F

12/16 03:02, 8年前 , 9F
clang 的 extension 有 closure 可以用
12/16 03:02, 9F

12/16 03:03, 8年前 , 10F
雖然說實際上不會去用它啦…
12/16 03:03, 10F

12/16 16:10, 8年前 , 11F
你講的區域變數是一個指標(先不理它特殊的身份),回傳就
12/16 16:10, 11F

12/16 16:12, 8年前 , 12F
是複製一份新的,像你的例子是把current最後的內容回傳
12/16 16:12, 12F

12/16 16:13, 8年前 , 13F
last_node,然後last_node裡面的內容就指著最後一個node
12/16 16:13, 13F

12/16 16:16, 8年前 , 14F
面 last_node->next = new_node;
12/16 16:16, 14F

12/16 16:17, 8年前 , 15F
的記憶體位置,然後你new的node就接在原來last_node的後
12/16 16:17, 15F

12/16 16:17, 8年前 , 16F
怎麼推文也可以亂掉XD
12/16 16:17, 16F

12/16 16:22, 8年前 , 17F
我猜你可能是和c++講的reference觀念混到了,如果是回傳
12/16 16:22, 17F

12/16 16:24, 8年前 , 18F
指定的內容是ref,回傳local variable就會出問題
12/16 16:24, 18F
※ 編輯: gowrite (123.195.54.122), 12/16/2017 17:13:43

12/16 18:04, 8年前 , 19F
我是認為原 PO 把「回傳指向區域變數的指標」
12/16 18:04, 19F

12/16 18:04, 8年前 , 20F
跟「回傳一個本身是指標的區域變數」搞混了
12/16 18:04, 20F

12/16 18:05, 8年前 , 21F
後者只要該指標不是前者的狀況那什麼事都沒有
12/16 18:05, 21F

12/16 18:06, 8年前 , 22F
就單純只是回傳一個區域變數的值而已, 只是恰巧該值是指標
12/16 18:06, 22F

01/02 22:44, 9年前 , 23F
問一個例子 你有個函數是把a+b回傳 你不回local怎麼做?
01/02 22:44, 23F

01/02 22:44, 9年前 , 24F
不要太鑽牛角尖 XD
01/02 22:44, 24F
文章代碼(AID): #1QD032Uj (C_and_CPP)