C 함수 선언에서 "..."는 마지막 매개 변수로서 무엇을 합니까?
다음과 같이 선언된 함수를 자주 볼 수 있습니다.
void Feeder(char *buff, ...)
"..."이 무슨 뜻입니까?
지정되지 않은 유형의 변수 수가 허용됩니다(예:printf
하고 있습니다).
접속할 수 있도록va_start
,va_arg
그리고.va_end
상세한 것에 대하여는, http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html 를 참조해 주세요.
variadic 함수(변수 파라미터)
#include <stdarg.h>
double average(int count, ...)
{
va_list ap;
int j;
double tot = 0;
va_start(ap, count); //Requires the last fixed parameter (to get the address)
for(j=0; j<count; j++)
tot+=va_arg(ap, double); //Requires the type to cast to. Increments ap to the next argument.
va_end(ap);
return tot/count;
}
기능...
마지막 매개변수를 Varadic 함수라고 합니다(Cppreference. 2016).이것....
는 지정되지 않은 유형의 가변 길이 파라미터를 허용하기 위해 사용합니다.
파라미터의 수나 타입이 불분명한 경우에는 바리에타디 함수를 사용할 수 있습니다.
가변 함수의 예:변수 개수의 합계를 반환하는 합함수가 필요하다고 가정합시다.여기서는 가변 함수를 사용할 수 있습니다.
#include <stdio.h>
#include <stdarg.h>
int sum(int count, ...)
{
int total, i, temp;
total = 0;
va_list args;
va_start(args, count);
for(i=0; i<count; i++)
{
temp = va_arg(args, int);
total += temp;
}
va_end(args);
return total;
}
int main()
{
int numbers[3] = {5, 10, 15};
// Get summation of all variables of the array
int sum_of_numbers = sum(3, numbers[0], numbers[1], numbers[2]);
printf("Sum of the array %d\n", sum_of_numbers);
// Get summation of last two numbers of the array
int partial_sum_of_numbers = sum(2, numbers[1], numbers[2]);
printf("Sum of the last two numbers of the array %d\n", partial_sum_of_numbers);
return 0;
}
출력:
연습 문제:가변 함수를 연습하기 위한 간단한 문제는 여기 해커랭크 연습 문제에서 찾을 수 있습니다.
레퍼런스:
- cppreference.(2016년 2월 13일).가변 함수https://en.cppreference.com/w/c/variadic에서 2018년 7월 25일 취득
변수 함수는 변수 개수의 인수를 사용할 수 있으며 마지막 매개 변수 대신 줄임표로 선언되는 함수입니다.이러한 함수의 예는 다음과 같습니다.
printf
.일반적인 선언은
int check(int a, double b, ...);
변수 함수에는 적어도 하나의 명명된 매개 변수가 있어야 합니다. 예를 들어 다음과 같습니다.
char *wrong(...);
C에서는 사용할 수 없습니다.
세 개의 점 '...'을 줄임표라고 한다.함수에서 이들을 사용하면 해당 함수는 가변 함수가 됩니다.함수 선언에서 이러한 파라미터를 사용한다는 것은 함수가 이미 정의된 파라미터 뒤에 임의의 수의 파라미터를 받아들인다는 것을 의미합니다.
예를 들어 다음과 같습니다.
Feeder("abc");
Feeder("abc", "def");
는 모두 유효한 함수 호출입니다.단, 다음과 같습니다.
Feeder();
이것은 가변 함수가 선언되고 있음을 의미합니다.
...
= 3점 = 3점 = 호출됨:ellipsis
- 평균: 변수 수 모수
- 일반 함수와 비교: 고정(지정된 수) 매개 변수
- 평균: 변수 수 모수
- 와 기능하다.
...
para는 다음과 같습니다.가변 함수
가변 함수
정의.
- 유효:
int validFunctionWithNamedParameterThenEllipsis(int a, double b, ...);
- 무효한
int invalidFunctionOnlyEllipsis(...);
예
일반적인 예:
int printf(const char *format, ...)
호출:
printf("year=%d, name=%s", 2021, "crifan");
->
format
=="year=%d, name=%s"
- 명명된 파라미터
...
==2021, "crifan"
- 변수 수
- 여기서 total 2 파라미터
- : first : " " "
2021
- : 유형 " " " " "
"crifan"
- : first : " " "
- 여기서 total 2 파라미터
- 변수 수
Varadic 함수의 파레미터 취득/계산 방법
- 로직:: 사용
va_list
, 를 사용하여, 를 참조해 주세요.va_start
,va_arg
,va_end
관련 정의
#include <stdarg.h>
void va_start(va_list ap, last_arg);
type va_arg(va_list ap, type);
void va_end(va list ap);
예
평균
#include <stdarg.h>
#include <stdio.h>
double average(int count, ...) {
va_list ap;
int j;
double sum = 0;
va_start(ap, count); /* Requires the last fixed parameter (to get the address) */
for (j = 0; j < count; j++) {
sum += va_arg(ap, int); /* Increments ap to the next argument. */
}
va_end(ap);
return sum / count;
}
int main(int argc, char const *argv[]) {
printf("%f\n", average(3, 1, 2, 3));
return 0;
}
최대값
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
int maxof(int, ...) ;
void f(void);
main(){
f();
exit(EXIT_SUCCESS);
}
int maxof(int n_args, ...){
register int i;
int max, a;
va_list ap;
va_start(ap, n_args);
max = va_arg(ap, int);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void) {
int i = 5;
int j[256];
j[42] = 24;
printf("%d\n",maxof(3, i, j[42], 0));
}
실행하다
#include <stdarg.h>
#define MAXARGS 31
/*
* execl is called by
* execl(file, arg1, arg2, ..., (char *)(0));
*/
int execl(const char *file, const char *args, ...)
{
va_list ap;
char *array[MAXARGS +1];
int argno = 0;
va_start(ap, args);
while (args != 0 && argno < MAXARGS)
{
array[argno++] = args;
args = va_arg(ap, const char *);
}
array[argno] = (char *) 0;
va_end(ap);
return execv(file, array);
}
내 경우: hook syscall()
/*==============================================================================
Hook: syscall()
==============================================================================*/
int syscall(int, ...);
// normally max number of syscall parameter is not exceed 8
// refer: https://opensource.apple.com/source/xnu/xnu-4570.1.46/bsd/kern/syscalls.master
int MaxSupportArgNum_syscall = 16;
%hookf(int, syscall, int number, ...){
os_log(OS_LOG_DEFAULT, "hook_syscall_stat_stat64: number=%d", number);
// Setting up some variables to get all the parameters from syscall
void *paraPtr, *paraList[MaxSupportArgNum_syscall];
// char *paraPtr, *paraList[MaxSupportArgNum_syscall];
va_list argList;
int curParaNum = 0;
va_start(argList, number);
while ((paraPtr = (void *) va_arg(argList, void *))) {
// while ((paraPtr = (char *) va_arg(argList, char *))) {
paraList[curParaNum] = paraPtr;
curParaNum += 1;
os_log(OS_LOG_DEFAULT, "hook_syscall_stat_stat64: [%d] paraPtr=%p", curParaNum, paraPtr);
}
va_end(argList);
// os_log(OS_LOG_DEFAULT, "hook_syscall_stat_stat64: argList=%{public}s", argList);
os_log(OS_LOG_DEFAULT, "hook_syscall_stat_stat64: curParaNum=%d", curParaNum);
bool isStat = (SYS_stat == number);
bool isStat64 = (SYS_stat64 == number);
if (isStat || isStat64){
char* curPath = (char *)paraList[0];
os_log(OS_LOG_DEFAULT, "hook_syscall_stat_stat64: isStat=%{bool}d, isStat64=%{BOOL}d, curPath=%{public}s", isStat, isStat64, curPath);
bool isJbPath = isJailbreakPath(curPath);
if (isJbPath){
os_log(OS_LOG_DEFAULT, "hook_syscall_stat_stat64: IS jailbreak path: %{public}s", curPath);
return OPEN_FAILED;
} else {
os_log(OS_LOG_DEFAULT, "hook_syscall_stat_stat64: NOT jailbreak path: %{public}s", curPath);
}
}
// return %orig;
// return %orig(number, ...);
// int retValue = %orig();
// int retValue = callOriginSyscall(number, curParaNum, paraList);
//// int retValue = callOriginSyscall(number, curParaNum, (void *)paraList);
// os_log(OS_LOG_DEFAULT, "hook_syscall_stat_file: retValue=%d", retValue);
// return retValue;
int paraNum = curParaNum;
int syscallRetValue = -1;
if (0 == paraNum){
syscallRetValue = %orig(number);
} else if (1 == paraNum){
void* para1 = paraList[0];
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: para1=%p", para1);
syscallRetValue = %orig(number, para1);
} else if (2 == paraNum){
void* para1 = paraList[0];
void* para2 = paraList[1];
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: para1=%p,para2=%p", para1, para2);
syscallRetValue = %orig(number, para1, para2);
} else if (3 == paraNum){
void* para1 = paraList[0];
void* para2 = paraList[1];
void* para3 = paraList[2];
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: para1=%p,para2=%p,para3=%p", para1, para2, para3);
syscallRetValue = %orig(number, para1, para2, para3);
} else if (4 == paraNum){
void* para1 = paraList[0];
void* para2 = paraList[1];
void* para3 = paraList[2];
void* para4 = paraList[3];
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: para1=%p,para2=%p,para3=%p,para4=%p", para1, para2, para3, para4);
syscallRetValue = %orig(number, para1, para2, para3, para4);
} else if (5 == paraNum){
void* para1 = paraList[0];
void* para2 = paraList[1];
void* para3 = paraList[2];
void* para4 = paraList[3];
void* para5 = paraList[4];
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: para1=%p,para2=%p,para3=%p,para4=%p,para5=%p", para1, para2, para3, para4, para5);
syscallRetValue = %orig(number, para1, para2, para3, para4, para5);
} else if (6 == paraNum){
void* para1 = paraList[0];
void* para2 = paraList[1];
void* para3 = paraList[2];
void* para4 = paraList[3];
void* para5 = paraList[4];
void* para6 = paraList[5];
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: para1=%p,para2=%p,para3=%p,para4=%p,para5=%p,para6=%p", para1, para2, para3, para4, para5, para6);
syscallRetValue = %orig(number, para1, para2, para3, para4, para5, para6);
} else if (7 == paraNum){
void* para1 = paraList[0];
void* para2 = paraList[1];
void* para3 = paraList[2];
void* para4 = paraList[3];
void* para5 = paraList[4];
void* para6 = paraList[5];
void* para7 = paraList[6];
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: para1=%p,para2=%p,para3=%p,para4=%p,para5=%p,para6=%p,para7=%p", para1, para2, para3, para4, para5, para6, para7);
syscallRetValue = %orig(number, para1, para2, para3, para4, para5, para6, para7);
} else if (8 == paraNum){
void* para1 = paraList[0];
void* para2 = paraList[1];
void* para3 = paraList[2];
void* para4 = paraList[3];
void* para5 = paraList[4];
void* para6 = paraList[5];
void* para7 = paraList[6];
void* para8 = paraList[7];
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: para1=%p,para2=%p,para3=%p,para4=%p,para5=%p,para6=%p,para7=%p,para8=%p", para1, para2, para3, para4, para5, para6, para7, para8);
syscallRetValue = %orig(number, para1, para2, para3, para4, para5, para6, para7, para8);
} else if (9 == paraNum){
void* para1 = paraList[0];
void* para2 = paraList[1];
void* para3 = paraList[2];
void* para4 = paraList[3];
void* para5 = paraList[4];
void* para6 = paraList[5];
void* para7 = paraList[6];
void* para8 = paraList[7];
void* para9 = paraList[8];
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: para1=%p,para2=%p,para3=%p,para4=%p,para5=%p,para6=%p,para7=%p,para8=%p,para9=%p", para1, para2, para3, para4, para5, para6, para7, para8, para9);
syscallRetValue = %orig(number, para1, para2, para3, para4, para5, para6, para7, para8, para9);
}
os_log(OS_LOG_DEFAULT, "hook_syscall_orig: syscallRetValue=%d", syscallRetValue);
return syscallRetValue;
}
주의사항
va_start
를 호출하는 va_start
,last_arg
는 첫 아닌 이름붙인 파라미터입니다.
상::int open(const char *path, int oflag, ...);
- ★★★★★★★★★★★★★★★★★★.
va_start(argList, oflag);
- 틀렸어
va_start(argList, path);
- (XCode) ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」
Second argument to 'va_start' is not the last named parameter
- (XCode) ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」
va_module
type va_arg(va_list ap, type);
type
하다
전달 시:
- 차
- 부호 없는 문자
- 부호 없는 쇼트
단, 반환은 항상 다음과 같습니다.
- 부호 없는 int
-> 코드:
curPara = (mode_t) va_arg(argList, mode_t);
다음과 같이 합니다.
#include <sys/stat.h>
#include <sys/types.h>
->mode_t
==unsigned short
등가:
curPara = (mode_t) va_arg(argList, unsigned short);
따라서 컴파일러 경고:
Second argument to 'va_arg' is of promotable type 'mode_t' (aka 'unsigned short'); this va_arg has undefined behavior because arguments will be promoted to 'int'
변경처:
curPara = (mode_t) va_arg(argList, unsigned int);
경고를 피할 수 있습니다.
관련 문서
- C Book : 변수 수(gbdirect.co.uk)
- 가변 함수 - Wikipedia
- <stdarg.h>(opengroup.org)
- stdarg.h - 위키백과
- C 라이브러리 - <stdarg>h>(tutorialspoint.com)
언급URL : https://stackoverflow.com/questions/2735587/in-a-c-function-declaration-what-does-as-the-last-parameter-do
'programing' 카테고리의 다른 글
org.internate 를 선택합니다.hql.internal.ast 입니다.QuerySyntaxException: 테이블이 매핑되지 않았습니다. (0) | 2022.09.04 |
---|---|
Java, Simplified는 int 배열에 int가 포함되어 있는지 확인합니다. (0) | 2022.09.04 |
Google App Engine에서 Java vs Python 선택 (0) | 2022.09.04 |
자바 이메일 주소의 가장 좋은 검증 방법은 무엇입니까? (0) | 2022.09.04 |
"java.security.cert" 수정 방법인증서.예외:제목 대체 이름이 없습니다" 오류입니까? (0) | 2022.09.04 |