Oft sehe ich eine Funktion, die so deklariert ist:
void Feeder(char *buff, ...)
Was bedeutet?
alaah
Oft sehe ich eine Funktion, die so deklariert ist:
void Feeder(char *buff, ...)
Was bedeutet?
es erlaubt eine variable Anzahl von Argumenten unspezifizierten Typs (wie z printf
tut).
Sie müssen mit darauf zugreifen va_start
, va_arg
und va_end
sehen http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html für mehr Informationen
N 1.1
Variadische Funktionen sind Funktionen, die eine variable Anzahl von Argumenten annehmen können und mit Auslassungspunkten anstelle des letzten Parameters deklariert werden. Ein Beispiel für eine solche Funktion ist
printf
.Eine typische Deklaration ist
int check(int a, double b, ...);
Variadische Funktionen müssen mindestens einen benannten Parameter haben, also zum Beispiel
char *wrong(...);
ist in C nicht erlaubt.
RvdK
variadische Funktion (mehrere Parameter)
#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;
}
dafmetal
Die drei Punkte „…“ werden Ellipsen genannt. Wenn Sie sie in einer Funktion verwenden, wird diese Funktion a variadisch Funktion. Sie in einer Funktionsdeklaration zu verwenden bedeutet, dass die Funktion eine beliebige Anzahl von Parametern nach den bereits definierten akzeptiert.
Zum Beispiel:
Feeder("abc");
Feeder("abc", "def");
sind alles gültige Funktionsaufrufe, das Folgende jedoch nicht:
Feeder();
Es bedeutet, dass a variadische Funktion wird deklariert.
arsch
Funktioniert mit ...
als letzter Parameter werden variadische Funktionen genannt (vgl. 2016). Dies ...
wird verwendet, um Parameter variabler Länge mit nicht spezifizierten Typen zuzulassen.
Wir können variadische Funktionen verwenden, wenn wir uns über die Anzahl der Parameter oder ihre Typen nicht sicher sind.
Beispiel für eine variadische Funktion:
Nehmen wir an, wir brauchen eine Summenfunktion, die die Summe der variablen Anzahl von Argumenten zurückgibt. Wir können hier eine variadische Funktion verwenden.
#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;
}
Ausgabe:
Übungsproblem: Ein einfaches Problem zum Üben der variadischen Funktion finden Sie in Hackerrank-Übungsproblem hier
Bezug:
Krifan
...
= drei Punkte = drei Punkte = aufgerufen: ellipsis
...
para heißt: Variadische Funktionint validFunctionWithNamedParameterThenEllipsis(int a, double b, ...);
int invalidFunctionOnlyEllipsis(...);
beliebter Fall:
int printf(const char *format, ...)
Anruf:
printf("year=%d, name=%s", 2021, "crifan");
->
format
== "year=%d, name=%s"
...
== 2021, "crifan"
2021
"crifan"
va_list
mit 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()
==============================================================================*/
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;
}
beim Anruf va_start
, last_arg
ist der zuletzt genannte Parameter, NICHT der erste
zum: int open(const char *path, int oflag, ...);
va_start(argList, oflag);
va_start(argList, path);
Second argument to 'va_start' is not the last named parameter
type va_arg(va_list ap, type);
für Pass type
gibt es einen Sonderfall:
beim Passieren:
aber zurück ist immer:
-> also beim Code:
curPara = (mode_t) va_arg(argList, mode_t);
gemäß:
#include <sys/stat.h>
#include <sys/types.h>
-> mode_t
==unsigned short
gleichwertig:
curPara = (mode_t) va_arg(argList, unsigned short);
Also Compiler-Warnung:
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'
ändern:
curPara = (mode_t) va_arg(argList, unsigned int);
Warnung vermeiden konnte.