0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C語言-函數(shù)的可變形參(不定形參)

DS小龍哥-嵌入式技術(shù) ? 來源:DS小龍哥-嵌入式技術(shù) ? 作者:DS小龍哥-嵌入式技 ? 2022-08-14 09:58 ? 次閱讀

1. 前言

在學(xué)習(xí)C語言函數(shù)章節(jié)時發(fā)現(xiàn),給函數(shù)傳入的形參必須和函數(shù)定義原型的類型、數(shù)量一致才可以正常調(diào)用。

平時使用的printfscanf等函數(shù)時,傳入的參數(shù)數(shù)量卻可以隨意改變,例如:

printf("大家好");
printf("我是整數(shù):%d\n",123);
printf("%d%d%d%d\n",1,2,3,4);
printf("%s%s%s\n","1","2","3","4");

printf函數(shù)是如何實現(xiàn)這種傳參方式的?

我們看一下printf,scanf系列函數(shù)的原型。

#include 
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);

#include 
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);

發(fā)現(xiàn)這些函數(shù)定義時,參數(shù)列表里有一個省略符號...,這個省略符號就表示當(dāng)前函數(shù)支持不定長形參

示例代碼:可變形參的聲明方式

#include 
#include 
#include 
void func(char *p,...);
int main(int argc,char **argv)
{
	func("123",1,2,3,4,"",12.345);
	return 0;
}

//正確的
void func(char *p,...)
{
	
}

//錯誤的
void func2(...,char *p)
{
	
}

//錯誤的
void func3(...)
{
	
}

2. 可變形參本身實現(xiàn)原理

明白了如何定義可變形參,接下來就得學(xué)習(xí)可變形參的原理,然后學(xué)習(xí)如何去提取這些傳入的參數(shù)。

(1). 函數(shù)的形參是放在??臻g的。

(2). 可變形參,傳入的多余的參數(shù)都是存放在??臻g。

存放內(nèi)存地址是連續(xù)的。

理論上只要知道傳入?yún)?shù)的首地址,就可以推出其他參數(shù)的地址。

系統(tǒng)的標準參數(shù)頭文件和處理可變形參的相關(guān)函數(shù)

#include 
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char  *str,  size_t  size,  const  char  *format,va_list ap);

直接查看頭文件的幫助:
[wbyq@wbyq linux_c]$ man stdarg.h
void va_start(va_list ap, argN);   //開始
void va_copy(va_list dest, va_list src); //拷貝
type va_arg(va_list ap, type);  //取具體形參—取值
void va_end(va_list ap);  //結(jié)束

va_list ap; 就是定義一個char類型的指針。va_list==char *

3. 單獨提取參數(shù)列表里的值

#include 
#include 
#include 
#include 

void foo(char *fmt, ...);
int main(int argc,char **argv)
{
	foo("%d,%s,%c",12,"123",'A');
	return 0;
}

// foo("%d,%s,%c",12,"123",'A')
void foo(char *fmt, ...)
{
   va_list ap;  //定義一個char類型指針
   int d;
   char c, *s;

   va_start(ap, fmt); //指針地址賦值--初始化
   while (*fmt)
	   switch (*fmt++) {
	   case 's':              /* string */
		   s = va_arg(ap, char *);
		   printf("string %s\n", s);
		   break;
	   case 'd':              /* int */
		   d = va_arg(ap, int);
		   printf("int %d\n", d);
		   break;
	   case 'c':              /* char */
		   c = (char) va_arg(ap, int);
		   printf("char %c\n", c);
		   break;
	   }
   va_end(ap); //將ap指針置為NULL
}

4. 使用格式化方式提取形參列表里的值

#include 
#include 
#include 
#include 

void foo(char *fmt, ...);
int main(int argc,char **argv)
{
	foo("int=%d,string=%s char=%c",12,"123",'A');
	return 0;
}

// foo("%d,%s,%c",12,"123",'A')
void foo(char *fmt, ...)
{
   char buff[100];
   va_list ap;  //定義一個char類型指針
   va_start(ap, fmt); //指針地址賦值--初始化
   //將參數(shù)列表里所有參數(shù),按照格式化轉(zhuǎn)換成字符串-存放到str指向的空間
   vsprintf(buff,fmt,ap);
   va_end(ap); //將ap指針置為NULL
   
   printf("%s\n",buff);
}

5. 提取可變形參列表里的單個數(shù)據(jù)

#include 
#include 
#include 
#include 

void foo(char *fmt, ...);
int main(int argc,char **argv)
{
	foo("sdcf","hello",666,'A',123.456);
	return 0;
}

void foo(char *fmt, ...)
{
   va_list ap;  //定義一個char類型指針
   int d;
   char c, *s;
   double f;
   
   va_start(ap, fmt); //指針地址賦值--初始化
   while(*fmt) //遍歷fmt指針指向空間的值
   {
		 switch(*fmt++) 
		{
			case 's':              /* string */
			   s = va_arg(ap, char *);
			   printf("字符串:%s\n", s);
			   break;
			case 'd':              /* int */
			   d = va_arg(ap, int);
			   printf("整型:%d\n", d);
			   break;
			case 'c':              /* char */
			   c = (char) va_arg(ap,int);
			   printf("字符:%c\n", c);
			   break;
			case 'f':              /* float */
			   f = va_arg(ap, double);
			   printf("浮點數(shù):%f\n", f);
			   break;
		}
   }
   va_end(ap); //將ap指針置為NULL
}

6. 精簡代碼-提取可變形參列表里的單個數(shù)據(jù)

#include 
#include 
#include 
#include 

void foo(char *fmt, ...);
int main(int argc,char **argv)
{
	foo("123","hello",666,'A',123.456);
	return 0;
}

void foo(char *fmt, ...)
{
   va_list ap;  //定義一個char類型指針
   va_start(ap, fmt); //指針地址賦值--初始化
   printf("第一個字符串:%s\n",fmt);
   printf("提取字符串:%s\n",va_arg(ap,char*));
   printf("提取整數(shù):%d\n",va_arg(ap,int));
   printf("提取字符:%c\n",va_arg(ap,int));
   printf("提取字符:%lf\n",va_arg(ap,double));
   va_end(ap); //將ap指針置為NULL
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • C語言
    +關(guān)注

    關(guān)注

    180

    文章

    7604

    瀏覽量

    136861
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4331

    瀏覽量

    62630
收藏 人收藏

    評論

    相關(guān)推薦

    C語言可變形是什么

    ??C語言允許定義參數(shù)數(shù)量可變函數(shù),這稱為可變參數(shù)函數(shù)(variadic function)。
    的頭像 發(fā)表于 08-18 21:40 ?1332次閱讀

    函數(shù)的實參與形

    。函數(shù)定義中指定的形,在未發(fā)生函數(shù)調(diào)用時不占內(nèi)存,只有函數(shù)調(diào)用時,函數(shù)中的形
    發(fā)表于 10-18 20:15

    單片機函數(shù)被改變的原因是什么?

    單片機函數(shù)被改變的原因是什么?
    發(fā)表于 10-19 07:03

    一種飛記錄數(shù)據(jù)解析軟件的設(shè)計與實現(xiàn)

    統(tǒng)的工作情況和各種飛行狀態(tài)的信息。一旦浮空器發(fā)生飛行故障,飛記錄數(shù)據(jù)為查找設(shè)備故障及失事原因提供重要依據(jù)。飛記錄數(shù)據(jù)解析軟件根據(jù)約定的傳輸協(xié)議,將特定形式的記錄數(shù)據(jù)解析為便于查看的記錄數(shù)據(jù),其解析的效率直
    發(fā)表于 11-11 17:29 ?5次下載
    一種飛<b class='flag-5'>參</b>記錄數(shù)據(jù)解析軟件的設(shè)計與實現(xiàn)

    C++語言入門教程之C++語言程序設(shè)計函數(shù)的詳細資料概述免費下載

    本文檔的主要內(nèi)容詳細介紹的是C++語言入門教程之C++語言程序設(shè)計函數(shù)的詳細資料概述免費下載內(nèi)容包括了:1
    發(fā)表于 09-20 14:51 ?23次下載

    C語言函數(shù)不改變形內(nèi)容的說明

    注:本文是作者以前發(fā)表在其個人博客,現(xiàn)在發(fā)布到“聚豐開發(fā)”專欄這也是面試時常碰到的題,通常是把一個指針作為函數(shù)的輸入?yún)?shù),在函數(shù)內(nèi)部會改變輸入?yún)?shù)對應(yīng)的指針,問面試者在函數(shù)調(diào)用過程中指針的具體內(nèi)容
    的頭像 發(fā)表于 10-29 11:01 ?4982次閱讀

    C語言總結(jié)_數(shù)組與函數(shù)練習(xí)題

    字符串標準處理函數(shù)介紹(string.h)、指針和數(shù)組當(dāng)做函數(shù),指針定義、函數(shù)返回指針、void類型定義指針、類型強制轉(zhuǎn)換、常量聲明、extern外邊引用聲明關(guān)鍵字。
    的頭像 發(fā)表于 08-14 09:36 ?831次閱讀

    C語言-函數(shù)的定義、聲明、傳

    C語言函數(shù)是非常重要的知識點,一個完整的C語言程序就是由主函數(shù)和各個子
    的頭像 發(fā)表于 08-14 09:57 ?1955次閱讀

    C語言-指針作為函數(shù)類型

    C語言函數(shù)里最常用就是指針傳和返回地址,特別是字符串處理中,經(jīng)常需要封裝各種功能函數(shù)完成數(shù)據(jù)處理。
    的頭像 發(fā)表于 08-14 10:05 ?1902次閱讀

    數(shù)組/指針的傳問題

    自定義函數(shù)里形的類型,要和函數(shù)調(diào)用中傳過去的實參類型相對應(yīng)
    的頭像 發(fā)表于 08-17 10:37 ?1084次閱讀

    關(guān)于征集《信息安全技術(shù) 散列函數(shù)》系列國家標準編單位的通知

    關(guān)于征集《信息安全技術(shù) 散列函數(shù) 第1部分 概述》標準編單位的通知 關(guān)于征集《信息安全技術(shù) 散列函數(shù) 第2部分 采用n位塊密碼的散列函數(shù)》標準
    的頭像 發(fā)表于 11-15 14:39 ?678次閱讀

    C語言函數(shù)調(diào)用的形式及過程

    C語言函數(shù)調(diào)用時的數(shù)據(jù)傳遞 在調(diào)用有函數(shù)時,主調(diào)函數(shù)和被調(diào)
    的頭像 發(fā)表于 03-10 14:28 ?1781次閱讀

    C語言函數(shù)參數(shù)介紹

    C語言數(shù)組元素作函數(shù)實參 數(shù)組元素可以用作函數(shù)實參,不能用作形。 C
    的頭像 發(fā)表于 03-10 14:30 ?2396次閱讀

    如何實現(xiàn)一個自己的printf函數(shù)代碼?

    C語言中,可變參數(shù)函數(shù)可變參數(shù)宏都允許函數(shù)或宏接受不定
    發(fā)表于 09-06 14:20 ?984次閱讀
    如何實現(xiàn)一個自己的printf<b class='flag-5'>函數(shù)</b>代碼?

    Python函數(shù)的分類

    的分類 形的分類可以分為六種: 帶有默認值的位置形 不帶默認值的位置形 帶有默認值的關(guān)鍵字形 不帶默認值的關(guān)鍵字形
    的頭像 發(fā)表于 11-14 11:19 ?829次閱讀