精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

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

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

1. 前言

在學習C語言函數章節時發現,給函數傳入的形參必須和函數定義原型的類型、數量一致才可以正常調用。

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

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

printf函數是如何實現這種傳參方式的?

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

#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, ...);

發現這些函數定義時,參數列表里有一個省略符號...,這個省略符號就表示當前函數支持不定長形參

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

#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. 可變形參本身實現原理

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

(1). 函數的形參是放在棧空間的。

(2). 可變形參,傳入的多余的參數都是存放在棧空間。

存放內存地址是連續的。

理論上只要知道傳入參數的首地址,就可以推出其他參數的地址。

系統的標準參數頭文件和處理可變形參的相關函數

#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);  //結束

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

3. 單獨提取參數列表里的值

#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); //指針地址賦值--初始化
   //將參數列表里所有參數,按照格式化轉換成字符串-存放到str指向的空間
   vsprintf(buff,fmt,ap);
   va_end(ap); //將ap指針置為NULL
   
   printf("%s\n",buff);
}

5. 提取可變形參列表里的單個數據

#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("浮點數:%f\n", f);
			   break;
		}
   }
   va_end(ap); //將ap指針置為NULL
}

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

#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("提取整數:%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
}
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • C語言
    +關注

    關注

    180

    文章

    7598

    瀏覽量

    136198
  • 函數
    +關注

    關注

    3

    文章

    4306

    瀏覽量

    62431
收藏 人收藏

    評論

    相關推薦

    C語言可變形是什么

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

    函數的實參與形

    函數定義中指定的形,在未發生函數調用時不占內存,只有函數調用時,函數中的形
    發表于 10-18 20:15

    單片機函數被改變的原因是什么?

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

    一種飛記錄數據解析軟件的設計與實現

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

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

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

    C語言函數不改變形內容的說明

    注:本文是作者以前發表在其個人博客,現在發布到“聚豐開發”專欄這也是面試時常碰到的題,通常是把一個指針作為函數的輸入參數,在函數內部會改變輸入參數對應的指針,問面試者在函數調用過程中指針的具體內容
    的頭像 發表于 10-29 11:01 ?4929次閱讀

    C語言總結_數組與函數練習題

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

    C語言-函數的定義、聲明、傳

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

    C語言-指針作為函數類型

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

    數組/指針的傳問題

    自定義函數里形的類型,要和函數調用中傳過去的實參類型相對應
    的頭像 發表于 08-17 10:37 ?1061次閱讀

    關于征集《信息安全技術 散列函數》系列國家標準編單位的通知

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

    C語言函數調用的形式及過程

    C語言函數調用時的數據傳遞 在調用有函數時,主調函數和被調
    的頭像 發表于 03-10 14:28 ?1614次閱讀

    C語言函數參數介紹

    C語言數組元素作函數實參 數組元素可以用作函數實參,不能用作形C
    的頭像 發表于 03-10 14:30 ?2312次閱讀

    如何實現一個自己的printf函數代碼?

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

    Python函數的分類

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