stdarg.h

stdarg.h

stdarg.h 는 C 프로그래밍 언어의 C 표준 라이브러리의 헤더로 함수가 무제한[1]인수를 받아들일 수 있도록 합니다.알 수 없는 번호 및 유형의 함수 인수 목록을 단계별로 살펴볼 수 있는 기능을 제공합니다.C++는 헤더에 이 기능을 제공합니다.cstdarg.

의 내용stdarg.h는 보통 바리에다 함수에 사용되지만 다른 함수에서는 사용할 수 있습니다(예를 들어,vprintf)를 호출합니다.

가변 함수를 선언하는 중

변수 함수는 변수 개수의 인수를 사용할 수 있으며 마지막 매개 변수 대신 줄임표로 선언되는 함수입니다.이러한 함수의 예는 다음과 같습니다.printf일반적인 선언은

인트 확인.(인트 a, 이중으로 하다 b, ...); 

변수 함수에는 적어도 하나의 명명된 매개 변수가 있어야 합니다. 예를 들어 다음과 같습니다.

 *틀렸어(...); 

C에서는 허용되지 않습니다.(C++에서는 이러한 선언이 허용됩니다.)C 에서는 생략 부호 앞에 콤마를 붙여야 합니다.C++ 에서는 생략 가능합니다.

가변 함수 정의

정의에서도 같은 구문이 사용됩니다.

 기능하다(, 이중으로 하다, 인트, ...);   기능하다( a, 이중으로 하다 b, 인트 c, ...) {     /* ... */ } 

줄임표는 이전 형식의 함수 정의에 나타나지 않을 수 있습니다.

stdarg.h 타입

이름. 묘사 호환성.
va_list 인수를 반복하기 위한 입력 C89

stdarg.h 매크로

이름. 묘사 호환성.
va_start 를 사용하여 인수 반복을 시작합니다.va_list C89
va_arg 인수를 취득하다 C89
va_end 프리 ava_list C89
va_copy 1개의 내용 복사va_list타인에게 C99

인수에 대한 액세스

이름 없는 인수에 액세스하려면 유형 변수를 선언해야 합니다.va_listvariadic 함수에서 사용됩니다.매크로va_start다음으로 2개의 인수를 사용하여 호출됩니다.첫 번째 인수는 이 유형의 선언된 변수입니다.va_list두 번째는 함수의 마지막 이름 있는 파라미터 이름입니다.그 후, 의 각 호출은va_argmacro는 다음 인수를 생성합니다.에 대한 첫 번째 주장va_argva_list두 번째는 함수에 전달되는 다음 인수 유형입니다.마지막으로,va_end에서 매크로를 호출해야 합니다.va_list(모든 인수를 읽을 필요는 없습니다.)

C99는 추가 매크로를 제공합니다.va_copy의 상태를 복제할 수 있습니다.va_list매크로 기동va_copy(va2, va1)카피va1안으로va2.

함수에 전달되는 이름 없는 인수의 수 또는 유형을 결정하기 위한 메커니즘은 정의되어 있지 않습니다.이 기능은 단순히 이를 알고 판단하기 위해 필요하며, 그 수단은 다양합니다.일반적인 표기법은 다음과 같습니다.

  • 의 사용방법printf또는scanf인수 유형을 나타내는 지정자가 포함된 형식 문자열과 같습니다.
  • variadic 인수 끝에 있는 sentinel 값.
  • 가변 인수의 수를 나타내는 카운트 인수.

이름 없는 인수를 다른 콜에 전달하다

이름 없는 인수 리스트의 사이즈는 일반적으로 알려져 있지 않기 때문에(대부분의 컴파일러에 의해 사용되는 호출규칙에서는 다음 명령어가 가리키는 이름 없는 인수 블록의 사이즈를 결정할 수 없습니다).va_list수신함수 내) 또한 이름 없는 인수를 다른 가변함수로 전송할 수 있는 신뢰할 수 있는 일반적인 방법이 없습니다.간접적인 수단(예를 들어 형식 문자열 해석)에 의해 인수 목록의 크기를 결정할 수 있는 경우에도fprintf())는 동적으로 결정된 인수의 수를 내부 가변 콜에 전달하는 휴대용 방법은 없습니다.이는 이러한 콜에 전달되는 인수의 수와 크기를 일반적으로 컴파일 시에 알 필요가 있기 때문입니다.이 제한은, 어느 정도, 가변 함수 대신에 가변 매크로를 채용하는 것으로 완화될 수 있습니다.또한 대부분의 표준 라이브러리 절차에서는 다음과 같은 기능을 제공합니다.v- 이름 없는 인수 목록에 대한 참조를 받아들이는 수정된 대체 버전(즉, 초기화됨)va_listvariable)을 지정합니다.예를들면,vfprintf()의 대체 버전입니다.fprintf()기대하다va_list실제 이름 없는 인수 목록 대신 사용할 수 있습니다.따라서 사용자 정의의 가변 함수는 다음 명령을 초기화할 수 있습니다.va_list변수 사용va_start이를 적절한 표준 라이브러리 함수에 전달하여 사실상 값 대신 참조에 의해 이름 없는 인수 목록을 전달합니다.C에서는 이름 없는 인수 목록을 값별로 전달할 수 있는 신뢰할 수 있는 방법이 없기 때문에 동등한 함수를 수용하지 않고 가변 API 함수를 제공합니다.va_list대신 나쁜 프로그래밍 관행으로 간주됩니다.

형식 안전

일부 C 구현에서는 컴파일러가 포맷 문자열 및 Sentinel의 올바른 사용을 확인할 수 있는 C 확장자를 제공합니다.이러한 확장자를 제외하고 컴파일러는 일반적으로 전달된 이름 없는 인수가 함수가 기대하는 유형인지 확인하거나 필요한 유형으로 변환할 수 없습니다.따라서 유형이 일치하지 않을 경우 정의되지 않은 동작이 발생하므로 이 점에서 정확성을 보장하기 위해 주의해야 합니다.예를 들어, 예상되는 유형이int *null 포인터는 다음과 같이 전달됩니다.(int *)NULL. 그냥 쓰고 있다.NULL다음 유형의 인수가 발생합니다.int또는void *둘 다 틀렸습니다.또 하나의 고려사항은 이름 없는 인수에 적용되는 기본 인수 프로모션입니다.afloat로 자동 승격됩니다.double. 마찬가지로, a보다 좁은 유형의 인수int로 승진할 것이다.int또는unsigned int. 이름 없는 인수를 수신하는 함수는 승격된 유형을 예상해야 합니다.

GCC에는 전달된 인수를 체크하는 확장이 있습니다.

format(archetype, string-index, first-to-check)

format Attribute는 함수가 다음을 수행하도록 지정합니다.printf,scanf,strftime또는strfmon형식 문자열과 대조하여 형식을 확인해야 하는 style 인수.예를 들어 다음과 같은 선언이 있습니다.

외부 인트 my_printf (무효 *my_object (my_object), 컨스턴트  *my_format, ...)       __param__ ((포맷 (인쇄물, 2, 3))); 

컴파일러는 콜의 인수를 체크합니다.my_printf와의 일관성을 유지하기 위해printfstyle format 문자열 인수my_format.

—.mw-parser-output cite.citation{font-style:상속을 하다;word-wrap:break-word}.mw-parser-output .citation q{인용:")"""\"""'""'"}.mw-parser-output .citation:target{background-color:rgba(0,127,255,0.133)}.mw-parser-output.id-lock-freea,.mw-parser-output .citation .cs1-lock-free{.배경:linear-gradient(transparent,transparent),url("//upload.wikimedia.org/wikipedia/commons/6/65/Lock-green.svg")right 0.1em center/9pxno-repeat}.mw-parser-output .id-lock-limiteda,.mw-parser-output .id-lock-registration a,.mw-parser-output .citation .cs1-lock-limiteda,.mw-parser-output .citation .cs1-lock-registration{.배경:linear-gradient(transparent,transparent),url("//upload.wikimedia.org/wikipedia/commons/d/d6/Lock-gray-alt-2.svg")right 0.1em center/9pxno-repeat}.mw-parser-output .id-lock-subscription a,.mw-parser-output .citation .cs1-lock-subscription{.배경:linear-gradient(transparent,transparent),url("//upload.wikimedia.org/wikipedia/commons/a/aa/Lock-red-alt-2.svg")right 0.1em center/9pxno-repeat}.mw-parser-output{배경 .cs1-ws-icon:linear-gradient(transparent,transparent),url("//upload.wikimedia.org/wikipedia/commons/4/4c/Wikisource-logo.svg")right 0.1emcenter/12pxno-repeat}.mw.-parser-output .cs1-code{색:상속을 하다;배경:상속을 하다;국경 아무 것도 없고 패딩: 물려받다}.mw-parser-output .cs1-hidden-error{디스플레이:아무도, 색:#d33}.mw-parser-output .cs1-visible-error{색:#d33}.mw-parser-output .cs1-maint{디스플레이:아무도, 색:#3a3, margin-left:0.3em}.mw-parser-output .cs1-format{:95%font-size}.mw-parser-output .cs1-kern-left{.Padding-left:0.2em}.mw-parser-output .cs1-kern-right{padding-right:0.2em}.mw-parser-output .citation .mw-selflinkᆪ"C언어 가족-Declaring에 5.27 확장 특성 함수".2009-01-03 Retrieved.

#실패하다 <stdio.h> #실패하다 <stdarg.h>  /* 네거티브 인수가 표시될 때까지 모든 arg를 한 번에 하나씩 인쇄합니다. 모든 arg는 int 타입 */으로 간주됩니다. 무효 인쇄물(인트 arg1, ...) {   va_list ap;   인트 i;    va_start(ap, arg1);    위해서 (i = arg1; i >= 0; i = va_module(ap, 인트))     인쇄물(%d, i);   va_end(ap);   풋차('\n'); }  인트 주된(무효) {    인쇄물(5, 2, 14, 84, 97, 15, -1, 48, -1);    인쇄물(84, 51, -1, 3);    인쇄물(-1);    인쇄물(1, -1);    돌아가다 0; } 

이 프로그램은 다음과 같이 출력합니다.

5 2 14 84 97 15 84 51  1

함수 내에서 다른 var args 함수(sprintf 등)를 호출하려면 함수의 var arg 버전(이 예에서는 vsprintf)을 사용해야 합니다.

무효 MyPrintf(컨스턴트  *포맷, ...) {   va_list args;    완충 장치[부후즈];    va_start(args, 포맷);   vsnprintf(완충 장치, 크기 완충 장치, 포맷, args);   va_end(args);   Flush Funny Stream(완충 장치); } 

varargs.h

오래된 버전의 POSIX가 레거시 헤더를 정의했습니다.varargs.hC의 표준화 이전부터의 것으로, 와 같은 기능을 제공합니다.stdarg.h이 헤더는 ISO C도 POSIX도 아닙니다. 파일에는 싱글 UNIX 사양의 두 번째 버전에서 정의된 대로 C89의 모든 기능이 포함되어 있습니다.stdarg.h단, 다음과 같은 예외는 있습니다.

  • 표준 C new-style 정의에서는 사용할 수 없습니다.
  • 지정된 인수를 생략할 수 있습니다(표준 C에는 적어도1개의 인수가 필요합니다).

인터페이스도 다릅니다.위해서printargs예를 들어, 대신 다음과 같이 쓸 수 있습니다.

#실패하다 <stdio.h> #실패하다 <변화.h>  /* "void" 유형은 없습니다. 암묵적인 int 반환을 사용하십시오.*/ 인쇄물(arg1, va_alist)   va_dcl /* 세미콜론은 없습니다!*/ {   va_list ap;   인트 i;    va_start(ap);    위해서 (i = arg1; i >= 0; i = va_module(ap, 인트))     인쇄물(%d, i);   va_end(ap);   풋차('\n');   돌아가다; } 

같은 방법으로 불리고 있습니다.

varargs.h에는 구현의 [2]동작방식으로 인해 구식 함수 정의가 필요합니다.반대로 구식 함수 정의와 를 혼재시킬 수 없습니다.stdarg.h.

레퍼런스

  1. ^ "IEEE Std 1003.1 stdarg.h". Retrieved 2009-07-04.
  2. ^ "Single UNIX Specification varargs.h". Retrieved 2007-08-01.