簡體   English   中英

va_end 到底是做什么用的? 是否總是需要調用它?

[英]What exactly is va_end for? Is it always necessary to call it?

va_end - 重置arg_ptr的宏。

訪問變量參數列表后,通常使用va_end()重置arg_ptr指針。 我知道如果您想重新迭代列表,它是必需的,但如果您不打算這樣做,真的需要它嗎? 這只是一種好的做法,比如“總是有一個default:在你的switch中”的規則嗎?

va_end用於進行清理。 你不想破壞堆棧,是嗎?

man va_start

va_end()

va_start() 的每次調用必須與同一 function 中的相應 va_end() 調用相匹配。 在調用 va_end(ap) 之后,變量 ap 未定義。 可以對列表進行多次遍歷,每次都由 va_start() 和 va_end() 括起來。 va_end() 可以是宏或 function。

注意單詞must的存在。

堆棧可能會損壞,因為您不知道va_start()在做什么 va_*宏被視為黑盒子。 每個平台上的每個編譯器都可以在那里為所欲為。 它可能什么都不做,也可能做很多事情。

一些 ABI 將前幾個參數傳遞到寄存器中,其余的傳遞到堆棧中。 一個va_arg()可能更復雜。 您可以查看給定實現如何執行可變參數,這可能很有趣,但在編寫可移植代碼時,您應該將它們視為不透明操作。

在 Linux x86-64 上,只能對va_list變量進行一次遍歷。 要進行更多遍歷,必須先使用va_copy進行復制。 man va_copy解釋了細節:

va_copy()

一個明顯的實現將有一個 va_list 是指向可變參數 function 的堆棧幀的指針。 在這樣的設置中(迄今為止最常見的),似乎沒有什么反對分配

 va_list aq = ap;

不幸的是,還有一些系統使它成為一個指針數組(長度為 1),並且需要

 va_list aq; *aq = *ap;

最后,在 arguments 在寄存器中傳遞的系統上,va_start() 可能需要分配 memory,存儲 arguments,並且還指示哪個參數是 next_arg 列表。 現在 va_end() 可以再次釋放分配的 memory。 為了適應這種情況,C99 增加了一個宏 va_copy(),這樣上面的賦值就可以替換為

 va_list aq; va_copy(aq, ap); ... va_end(aq);

va_copy() 的每次調用都必須與同一 function 中相應的 va_end() 調用相匹配。 一些不提供 va_copy() 的系統改為使用 __va_copy,因為這是提案草案中使用的名稱。

在常見的“堆棧上傳遞的參數”實現中,我相信 va_end() 通常是空/空/空。 但是,在傳統方案較少的平台上,它變得很有必要。 包含它以保持平台中立是一種“良好做法”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM