【C/C++開發】C語言實現函數可變參數

? ? ? ?函數原型: int printf(const char *format[,argument]...)
?????? 返 回 值: 成功則返回實際輸出的字符數,失敗返回-1.
?函數說明:
???????在printf()函數中,format后面的參數個數不確定,且類型也不確定,這些參數都存放在棧內.調用printf()函數時,根據format里的格式("%d %f...")依次將棧里參數取出.而取出動作要用到va_arg、va_end、va_start這三個宏定義,再加上va_list.
???? (1)va_list事實上是一char *類型,即:
??????????? typedef char* va_list;
???? (2)三個宏定義:
??????????? #define _INTSIZEOF(n)??? ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )?
????????????#define va_start(ap,v)???? ( ap = (va_list)&v + _INTSIZEOF(v) )?
????????????#define va_arg(ap,type)? ( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )?
????????????#define va_end(ap)????????? ( ap = (va_list)0 )?
?? 【attention】C語言中可變參數的原理---printf()函數?
??????????? int printf(const char* format,...);???
????? 使用過C語言的人所再熟悉不過的printf函數原型,它的參數中就有固定參數format和可變參數(用”…”表示).而程序員又可以用各種方式來調用printf,如:?
??????????? printf("%d ",value);???
??????????? printf("%s ",str); ??

??????????? printf("the number is %d,string is:%s ",value,str);?
?????? 可以看出,該函數的參數格式不固定,參數類型不固定.在C語言中使用宏來處理這些可變參數.這些宏看起來很復雜,其實原理挺簡單,即根據參數入棧的特點從最靠近第一個可變參數的固定參數開始,依次獲取每個可變參數的地址.
?(1)宏va_start
????? 通過該宏定義可以獲取到可變參數表的首地址,并將該地址賦給指針ap.
?(2)宏va_arg
????? 通過該宏定義可以獲取當前ap所指向的可變參數,并將指針ap指向下一個可變參數.注意,該宏的第二個參數為類型.
?(3)宏va_end
??????通過該宏定義可以結束可變參數的獲取.


????? 程序員通過這三個宏定義就可以實現對可變參數的處理.例如:


? ?#include <stdio.h> ?
??
typedef char* va_list; ??
? ?#define _INTSIZEOF(n) ? ?((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) ) ??
? ?#define va_start(ap,v) ? ( ap = (va_list)&v + _INTSIZEOF(v) ) ??
? ?#define va_arg(ap,type) ?( *(type *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) ??
? ?#define va_end(ap) ? ? ? ( ap = (va_list)0 ) ??
??
int cal_val(int c, ...) ??
{ ??
? ? int sum = c; ??
? ? va_list ap; ? ? ? ? ? ? ?//聲明指向char型的指針 ?
? ? va_start(ap,c); ? ? ? ? ?//獲取可變參數列表的首地址,并賦給指針ap ?
??
? ? c = va_arg(ap,int); ? ? ?//從可變參數列表中獲取到第一個參數(返回值即為參數) ?
? ? while(0 != c) ??
? ? { ??
? ? ? ? sum += c; ??
? ? ? ? c = va_arg(ap,int); ?//循環的從可變參數列表中獲取到參數(返回值即為參數) ?
? ? } ?
? ? va_end(ap); ? ? ? ? ? ? ?//結束從可變參數列表中獲取參數 ?
? ? return sum; ??
} ? ?
? ?
int main(int argc, char* argv[]) ??
{ ??
? ? int value1; ?
? ? ??
? ? value1 = cal_val(1,2,3,4,5,6,7,8,9,0); ??
? ? printf("value1=%d/n",value1); ?
? ? value2 = cal_val(6,7,8,9,0); ??
? ? printf("value2=%d/n",value2); ?
? ? ??
? ? return 0; ??
} ??


轉載于:https://www.cnblogs.com/huty/p/8517288.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/372781.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/372781.shtml
英文地址,請注明出處:http://en.pswp.cn/news/372781.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java postgresql json_java – 將PostgreSQL JSON列映射到Hibernate值類...

See PgJDBC bug #265.PostgreSQL對數據類型轉換過于嚴格,非常嚴格.它不會隱式地將文本轉換為類似文本的值,例如xml和json.解決此問題的嚴格正確方法是編寫使用JDBC setObject方法的自定義Hibernate映射類型.這可能有點麻煩,所以你可能只想通過創建一個較弱的強制轉換來使Postgr…

面向接口編程詳解(三)——模式研究

通過前面兩篇&#xff0c;我想各位朋友對“面向接口編程”的思想有了一定認識&#xff0c;并通過第二篇的例子&#xff0c;獲得了一定的直觀印象。但是&#xff0c;第二篇中的例子旨在展示面向接口編程的實現方法&#xff0c;比較簡單&#xff0c;不能體現出面向接口編程的優勢…

錯誤學習:Java + OSGi

最近&#xff0c;我致力于在OSGi環境中使Apache Hive工作。 雖然沒有被證明是小菜一碟&#xff08;軟件對嗎&#xff1f;。。為什么我不感到驚訝&#xff1f; &#xff09;&#xff0c;它引導我解決了各種Java和OSGi錯誤。 在這里&#xff0c;我列出了其中一些讓我有些吃力的東…

iOS多Targets管理

序言&#xff1a; 個人不善于寫東西&#xff0c;就直奔主題了。 其實今天會注意到多targets這個東西&#xff0c;是因為在學習一個第三方庫FBMemoryProfiler的時候&#xff0c;用到了&#xff0c;所以就搜索了一些相關資料&#xff0c;就在這里記錄一下。 可能每個人都會遇到這…

優化的34條定律

1.Minimize HTTP Requests 減少HTTP請求 圖片、css、script、flash等等這些都會增加http請求數&#xff0c;減少這些元素的數量就能減少響應時間。把多個JS、CSS在可能的情況下寫進一個文件&#xff0c;頁面里直接寫入圖片也是不好的做法&#xff0c;應該寫進CSS里&#xff0c;…

休眠提示:排序和排序

讓我們介紹另一個休眠性能提示。 你還記得以前的休眠的模式后 &#xff1f; 我們有一個與一對多協會有關的星際飛船和軍官。 Entity public class Starship {Id GeneratedValue(strategyGenerationType.SEQUENCE) private Long id;public Long getId() {return id;}protected v…

java 基本類型 線程安全_java的基本類型和i++線程安全性的深入解析

在java中&#xff0c;除了long和double的8個字節、64位比特的變量外&#xff0c;其他的基本變量都是原子性的。java存儲模型要求獲取和存儲操作都為原子性&#xff0c;但是對于非volatile的long和double變量&#xff0c;jvm允許將64位的讀或寫劃分為兩個32位的操作。如果讀和寫…

MySQL配置文件mysql.ini參數詳解

my.ini&#xff08;Linux系統下是my.cnf&#xff09;&#xff0c;當mysql服務器啟動時它會讀取這個文件&#xff0c;設置相關的運行環境參數。 my.ini分為兩塊&#xff1a;Client Section和Server Section。 Client Section用來配置MySQL客戶端參數。 要查看配置參數可以用下面…

微信公眾平臺和微信開放平臺的區別

自己也剛開始做微信開發&#xff0c;先寫寫自己的認識&#xff1a; 用微信公眾平臺可以做手機端H5頁面的微信登錄&#xff0c;微信支付 用微信開放平臺可以做PC端網頁的微信登錄。 轉載于:https://www.cnblogs.com/mafeng/p/5610770.html

java 傳遞bean_如何將bean作為參數傳遞給JSP標記?

我ve created a custom JSP tag that is supposed to accept a list of products to render, but I我無法弄清楚如何將列表傳遞給標簽 . 產品列表作為頁面范圍的bean存在 . Web應用程序使用Struts taglib在Struts 1.2.x中編寫 .這是我的代碼的簡化版本&#xff1a;renderProduc…

Business Component(BC)和Business Object(BO)

Siebel應用架構的一個成功的地方就是在應用里引入了BC&#xff0c;BO的概念&#xff0c;從而使得幾千張關系數據表能夠按照業務的含義組織成業務對象&#xff0c;對于業務人員而言具有了業務上的含義&#xff0c;而不僅僅是從技術人員的觀點來對待數據&#xff08;就是關系表而…

NetBeans可用性提示

的Java IDE都來了&#xff0c;因為在很長的路要走天的JBuilder的 &#xff08;盡管JBuilder中似乎是一個值得歡迎提前在時間&#xff09;。 當今的Java IDE&#xff08;例如NetBeans &#xff0c; Eclipse &#xff0c; IntelliJ IDEA和JDeveloper &#xff09;是非常先進的工具…

一個JVM進程啟動后里面有幾個線程

在寫Java程序時&#xff0c;通常我們管只有一個main函數&#xff08;而沒有別的Thread或Runnable的程序&#xff09;叫單線程程序。但是我們寫的這個所謂的單線程程序只是JVM這個程序中的一個線程&#xff0c;JVM本身是一個多線程的程序&#xff0c;至少得有一個垃圾收集器線程…

WPF 反編譯后錯誤處理

1. 首先&#xff0c;手動創建一個WPF工程&#xff08;WpfApplicationReflectorDemo&#xff09; 2. 把生成的WpfApplicationReflectorDemo.exe 拖到ILSpy里 3.點擊 File -> Save Code...: 相應的代碼會生成到指定地方。 4. 打開應用程序&#xff0c;并且編譯它&#xff0c;此…

JavaFX 2 GameTutorial第1部分

介紹 我相信大多數軟件開發人員可能會在年輕人&#xff08;年輕人&#xff09;一生中的某一時刻被迫創建游戲來幫助他們學習編程語言&#xff08;我知道我確實做到了&#xff09;。 以前&#xff0c;我的第一臺計算機實際上是Franklin Ace 1000 &#xff0c;后來是Apple [] 。 …

虛擬現實-VR-UE4-認識UE4

VR的火熱&#xff0c;讓每個人都想參與一下&#xff0c; 公司在展會上面搞了一個VR的Demo&#xff0c;關注度超出預期&#xff0c;使得公司高層決定來個VR項目 所以 關于UE4 百度百科地址&#xff1a;http://baike.baidu.com/link?urlmEmbwOcqEuqtkfdu9lNdxVtWAkv0Q6UHZ4VgIHr…

java concurrent 例子_[Java Concurrent] 并發訪問共享資源的簡單案例

EvenGenerator 是一個偶數生成器&#xff0c;每調用一個 next() 就會加 2 并返回疊加后結果。在本案例中&#xff0c;充當被共享的資源。EvenChecker 實現了 Runnable 接口&#xff0c;可以啟動新的線程執行 run() 任務&#xff0c;用于檢測所指向的偶數生成器是否每次都返回偶…

OSGI實戰第一章

第一章 解開OSGI的面紗 OSGI是什么&#xff1f;是Java平臺的一個模塊化層。模塊化&#xff1a;軟件應用程序的代碼被分割為表示獨立內容的邏輯單元&#xff0c;可簡化開發&#xff0c;可通過強化邏輯模塊的界限來提高可維護性。Java模塊化的不足a) Java使用訪問…

輕松完成Birt報告

這是使用Birt插件在Eclipse中構建報告的完整指南。 Birt或Business Intelligence and Reporting工具是一種無需編寫太多Java代碼即可生成報告的工具。 如果您使用的是ireport&#xff0c;那么您知道我在說什么&#xff1a;&#xff09;&#xff08;晶體報告..毫無意義&#xff…

MySQL 的 RowNum 實現

MySQL 下面沒有RowNum&#xff0c;排序后序號卻無法得到&#xff0c;比較麻煩&#xff01; SELECT rownum:rownum1 rownum, CollectSn From(SELECT rownum:0,bbgmain.* FROM qbdb.bbgmain WHERE collectsn! ORDER BY collectsn limit 10) t轉載于:https://www.cnblogs.com/hym-…