生活随笔
收集整理的這篇文章主要介紹了
C语言 可变参数函数 tcy
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
可變參數函數 ? ? ??
1.1.格式:int add(int n, ...)
1.2.參數:n:強制參數(必須至少一個)...:可選參數類型可變化
?
2.stdarg.h :
void va_start( va_list arg_ptr, prev_param );?type va_arg( va_list arg_ptr, type );?void va_end( va_list arg_ptr );va_list: variable-argument(可變參數)?用途:用來保存宏va_start、va_arg和va_end所需信息的一種類型為訪問變長參數列表中參數必聲明 va_list 類型對象定義:?typedef char * va_list;void va_start(va_list argptr,prev_param);//宏用途:訪問變長參數列表中的參數之前使用的宏它初始化用 va_list 聲明的對象,初始化結果供宏 va_arg 和 va_end 使用說明:參數1初始化argptr參數指針參數2必須是該函數最后一個有名稱參數的名稱type va_arg(va_list argptr, type);用途:展開成一個表達式的宏,該表達式具有變長參數列表中下一個參數的值和類型。每次調用 va_arg 都會修改用 va_list 聲明的對象,從而使該對象指向參數列表中的下一個參數說明:得到當前argptr所引用可選參數,也會將argptr移動到列表下一個參數參數2是剛剛被讀入的參數類型void va_end(va_list argptr);用途:該宏使程序能夠從變長參數列表用宏 va_start 引用的函數中正常返回說明:不再需要使用參數指針時必須調用宏 va_end如用va_start或va_copy來重新初始化一個之前用過參數指針,也必須先調用宏 va_endvoid va_copy(va_list dest, va_list src);用當前的 src值來初始化參數指針dest然后就可以使用 dest 中的備份獲取可選參數列表,從src 所引用的位置開始
3.實例
實例1.1:.int add(int n, ...) ? ? // 參數:第一個強制參數指定int可選參數數量#include <stdio.h>#include <stdarg.h>int add(int n, ...) {int i = 0, sum = 0;va_list argptr;//創建 va_list 類型變量va_start(argptr, n); ? ?// 用 int 參數和 va_start 宏來初始化 va_list 變量為一個參數列表for (i = 0; i < n; ++i) ? ? ? ? ? ? ? ? ? ? ?// 對每個可選參數,讀取類型為int的參數,sum += va_arg(argptr, int); ? ? // 訪問參數列表中的每個項va_end(argptr);//清理賦予 va_list 變量的內存return sum;}void view(int n, ...) {va_list argptr;va_start(argptr, n);printf("%d\n", va_arg(argptr, int));printf("%f\n", va_arg(argptr, double));printf("%s\n", va_arg(argptr, char*));va_end(argptr);}int main() {printf("%d\n", add(3, 1, 2, 3));//6view(3, (int)3, (double)3.14, "Tom");//3 3.140000 Tom}
實例1.2:#include <stdio.h>#include <stdarg.h>#include <string.h>void print(const char *msg, ...) {va_list args; ? ? ? ? ? ? ? ? ? ? ? ? /* 定義保存函數參數的結構 */int argno = 0; ? ? ? ? ? ? ? ? ? ? ? /* 紀錄參數個數 */char *pstr; ? ? ? ? ? ? ? ? ? ? ? ? ?/* 存放取出的字符串參數 */va_start(args, msg); ? ? ? ? ? /* args指向傳入的第一個可選參數,msg是最后一個確定的參數 */while (1) {pstr = va_arg(args, char *); ?/* 取出當前的參數,類型為char *. */if (strcmp(pstr, "/0") == 0)break; ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 采用空串指示參數輸入結束 */printf("parameter%d=%s;\n", argno, pstr);argno++;}va_end(args); ? ? ? ? ? ? ? ? ? ? ? /* 將args置為NULL */}int main(void) { print("print", "This", "is", "a", "print!", "33", "/0"); }//parameter0 = This;//parameter1 = is;//parameter2 = a;//parameter3 = print!;//parameter4 = 33;
實例3:實現原理// 64/32位機器時加8內存大小8/4字節對齊#define X64#ifdef X64#define T long long //sizeof(long long int)=8#else#define T int ? ? ? //sizeof(int)=4#endifsize_t offset_adr = sizeof(T);//8//VA_LIST套宏中可以使用,用來改變INTSIZEOF中t的類型//固定參數void test(int a, double b, const char* c,long long d,long double e){char *p = (char*)&a;//&a = void*類型需轉換,void * =&a不需轉換但使用時要轉換printf("%p %p %p %p %p\n", &a, &b, &c,&d,&e);//0000003AD119FC80 0000003AD119FC88 0000003AD119FC90 0000003AD119FC98 0000003AD119FCA0void *pvoid = &a;printf("%d\n", *((int*)&a)); ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //10printf("%fL\n", *((double*)((char*)p + offset_adr *1))); ? ? //20.000000Lprintf("%s\n", *((char**)(p + offset_adr *2))); ? ? ? ? ? ? ?//Tomprintf("%lld\n", *((long long*)((char*)p + offset_adr *3))); //30printf("%fL\n", *((long double*)((char*)p + offset_adr *4)));//40.000000L}//可變參數void test1(const char* s, const char *str, ...){char *p = (char*)&s;printf("%p %p %p %p\n", p, &s, &str, p + offset_adr);printf("%s\n", *(char**)p); ? ? ? ? ? ? ? ?//10printf(" %d\n", *(int*)(p + offset_adr)); ?//- 845046652printf(" %s\n", *(char**)(p + offset_adr));//Bob}int main(){const char *p = "Hello world";void *ptr = &p;printf("%s\n", *(char**)ptr);//Hello worldtest(10, 20.0, "Tom",30,40.0);test1("10", "Bob", 20, 30.0,40,50.0);return 0;}
??
總結
以上是生活随笔為你收集整理的C语言 可变参数函数 tcy的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。