麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Linux下C庫(kù)學(xué)習(xí) - stdarg.h

2019-11-10 20:16:54
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

想要函數(shù)使用可變參數(shù),那就必須要包含stdarg.h這個(gè)頭文件,簡(jiǎn)單就不說(shuō)了,我們重新來(lái)看看可變參數(shù)的定義和使用吧。

1.聲明可變參數(shù)

可變參數(shù)的聲明有兩點(diǎn)

使用‘…’來(lái)代表可變參數(shù)可變參數(shù)之前必須有一個(gè)命名的參數(shù)

簡(jiǎn)單說(shuō)就是如果你想聲明一個(gè)可變參數(shù)的函數(shù),那么有兩種形式

func(...) //錯(cuò)誤,前面必須有一個(gè)命名的參數(shù)func(xxx,...) //正確,xxx可以用任意的參數(shù)代替,比如char *name,int i都可以

2.定義可變參數(shù)

可變參數(shù)的定義和聲明相同,兩者保持一致即可

3.可變參數(shù)的使用

要使用可變參數(shù),主要會(huì)用到下列幾個(gè)函數(shù)

#include <stdarg.h>void va_start(va_list ap, last);type va_arg(va_list ap, type);void va_end(va_list ap);void va_copy(va_list dest, va_list src);

這里四個(gè)函數(shù)是參考man手冊(cè)上的,最后的va_copy沒(méi)有用過(guò),不太清楚什么情況下需要使用,麻煩各位在留言賜教 剩下的三個(gè)我們來(lái)一個(gè)一個(gè)看,這里舉個(gè)簡(jiǎn)單的例子方便講解

#include <stdio.h>#include <stdarg.h>void fun(char *name, ...){ va_list pa; int a, b; char *c; double d; va_start(pa, name); a = va_arg(pa, int); b = va_arg(pa, int); c = va_arg(pa, char *); d = va_arg(pa, double); va_end(pa); 可以看到,要使用可變參數(shù),首先需要定義一個(gè)va_list類(lèi)型的變量,這個(gè)變量就相當(dāng)于是指向可變參數(shù)列表的指針,通過(guò)va_start函數(shù)將這個(gè)指針賦值,后面就可以通過(guò)va_arg來(lái)獲取每一個(gè)參數(shù)。

va_arg的函數(shù)原型里面有個(gè)type,這個(gè)type類(lèi)型怎么理解呢? 大家可以這樣理解,因?yàn)榭勺儏?shù)是沒(méi)有聲明參數(shù)類(lèi)型的,那么編譯器怎么去檢測(cè)到底類(lèi)型是否匹配呢?最簡(jiǎn)單的辦法就是向上提升,比如

float類(lèi)型的實(shí)際參數(shù)將提升到doublechar、short和相應(yīng)的signed、unsigned類(lèi)型的實(shí)際參數(shù)提升到int如果int不能存儲(chǔ)原值,則提升到unsigned int

由于默認(rèn)肯定會(huì)向上提升,所以一定要盡量避免以下類(lèi)型的參數(shù) type絕對(duì)不能為以下類(lèi)型:

char、signed char、unsigned charshort、unsigned shortsigned short、short int、signed short int、unsigned short intfloat

因此在示例中,第一個(gè)int類(lèi)型的數(shù)字我用int類(lèi)型接收,第二個(gè)字符我依然使用int類(lèi)型來(lái)接收,第三個(gè)字符串就必須使用char *類(lèi)型的接收,第四個(gè)浮點(diǎn)型使用double類(lèi)型來(lái)接收,如果你不小心寫(xiě)錯(cuò)了類(lèi)型,系統(tǒng)的提示如下(這里我把示例中的double改成了float)

test.c: In function ‘fun’:test.c:17:20: warning: ‘float’ is promoted to ‘double’ when passed through ‘...’ [enabled by default] d = va_arg(pa, float); ^test.c:17:20: note: (so you should pass ‘double’ not ‘float’ to ‘va_arg’)test.c:17:20: note: if this code is reached, the program will abort

最后的va_end就相當(dāng)于是結(jié)束標(biāo)記,一個(gè)va_start必須和一個(gè)va_end對(duì)應(yīng)起來(lái)使用才可以。

使用的話(huà)我想大家應(yīng)該都會(huì),那具體原理是什么樣的呢? 要搞清楚原理,首先需要知道參數(shù)到底是怎么傳遞進(jìn)來(lái)的,事實(shí)上,在進(jìn)程中,堆棧地址時(shí)由高向低分配的,在調(diào)用參數(shù)的時(shí)候,首先入棧的函數(shù)參數(shù),接下來(lái)是函數(shù)的返回地址,再下來(lái)是函數(shù)的執(zhí)行代碼,而參數(shù)的入棧順序是先入最后一個(gè)參數(shù),最后入第一個(gè)參數(shù)

這里寫(xiě)圖片描述

如上圖所示,參數(shù)在堆棧的排列是從高地址向低地址的,實(shí)際上具體是宏定義如下

typedef char * va_list; // x86平臺(tái)下va_list的定義#define va_start(ap, v) ( ap = (va_list)&v + _INTSIZEOF(v) ) //第一個(gè)可選參數(shù)地址#define va_arg(ap, t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) ) //下一個(gè)參數(shù)地址#define va_end(ap) ( ap = (va_list)0 ) // 將指針置為無(wú)效

這里有個(gè)宏_INTSIZEOF需要特別介紹下,這個(gè)宏是為了求出變量所占內(nèi)存空間的大小,具體實(shí)現(xiàn)如下

#define _INTSIZEOF(n) ((sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

網(wǎng)上有位大神對(duì)這個(gè)函數(shù)又深刻的理解,大家可以去看看他的文章_INTSIZEOF(n)這個(gè)函數(shù)簡(jiǎn)單說(shuō)就是把n轉(zhuǎn)化成int的整數(shù)倍,來(lái)實(shí)現(xiàn)格式對(duì)齊,明白了這里,我們接著往下看

va_start 這個(gè)應(yīng)該很好理解,就是說(shuō)固定參數(shù)的地址加上他本身的內(nèi)存大小,結(jié)合上面的圖也就是第一個(gè)可變參數(shù)的地址,這樣ap就指向了第一個(gè)可變參數(shù),后面我們通過(guò)ap就可以得到其他的參數(shù)

va_arg 這個(gè)宏寫(xiě)的有些復(fù)雜,我們需要把它拆成兩部分看 1. ap += _INTSIZEOF(t); // 此時(shí)指針ap已經(jīng)指向下一個(gè)參數(shù)了 /* ap減去當(dāng)前參數(shù)的大小得到當(dāng)前參數(shù)的地址,再把地址強(qiáng)制類(lèi)型轉(zhuǎn)換后返回它的值 */ 2. return (t )( ap - _INTSIZEOF(t)) 通過(guò)第一步我們讓指針ap指向了后一個(gè)參數(shù),通過(guò)第二步返回了當(dāng)前的參數(shù)

va_end 這個(gè)宏很簡(jiǎn)單,就是清空了指針,記著需要和va_start配套使用

看了C語(yǔ)言的具體實(shí)現(xiàn),不得不感嘆,大神們真的是把指針使用的淋漓盡致,不過(guò)任何事情都有兩方面,這樣做雖然高效快捷,但同時(shí)也留下了不小的安全隱患

參考文檔 深入淺出va函數(shù) 關(guān)于va_arg中的type


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 国产一区二区三区色淫影院 | 亚洲综合色视频在线观看 | 视频一区二区三区中文字幕 | 亚洲午夜网站 | 欧美成人激情在线 | av在线高清观看 | 九九色网站 | 9797色| 国产视频在线免费观看 | 色妞视频男女视频 | 黄色视品| 成人三区四区 | 国产亚洲精品久久久久久网站 | 久久艹逼| 黄色网址免费在线播放 | 久久免费视频5 | 国产成人自拍av | 99这里精品| av电影在线观看网址 | 欧美h版电影在线观看 | 国产精品成人免费一区久久羞羞 | 欧美高清在线精品一区二区不卡 | 久久久久久久免费视频 | 中国成人在线视频 | 日韩视频一区 | 高清在线观看av | 泰剧19禁啪啪无遮挡大尺度 | 91 免费看片| 久草视频福利在线观看 | 欧美视频一区二区三区在线观看 | www.com超碰| 欧美一级淫片a免费播放口 91九色蝌蚪国产 | 国产麻豆交换夫妇 | 国产一区二区国产 | 精品国产一区二区三区久久久蜜月 | 欧美精品1区 | 精品亚洲va在线va天堂资源站 | 成年人在线视频 | 国产精品视频在 | 国产成人av免费 | 性感美女一级毛片 |