Variable parameters.
1: Must have an advance parameter, (ie: ...) You must have a parameter before you can calculate the address of the first unknown parameter that follows. Once you know the address of the first unknown parameter, you can format the string according to FMT and then compute the remaining parameter addresses in turn.
sprintf () Prototype: sprintf (char* buffer, const char* FMT, ...), where FMT is the advance parameter
2: Each variable elaboration function, its creator and the user must have one parameter's use convention. Otherwise, it will be messed up.
3: Technical basis for the implementation of variable functions
1: All parameters, at the assembly level, are of an integer multiple of 4 bytes. The Char,short type is also extended to 4byte
The technique of extending the type of any length into a 4byte integer multiple is
_intsizeof (n) ((sizeof (n) +sizeof (int)-1) & ~ (sizeof (int)-1))
Simplification is, ((sizeof (n) +4-1) & ~ (4-1))
_intsizeof (char*) = 4
_intsizeof (2byte) = 4
_intsizeof (double) = 8
2: With the above knowledge, here is a parameter from a variable parameter
#define VA_START (AP,V) (AP = (va_list) &v + _intsizeof (v))
: Gets the address of the known parameter,
The AP is the first unknown parameter address, and V is the aforementioned advance parameter FMT
Eg:fun (int n,...) v is the address of N.
#define VA_ARG (ap,t) \
(* (t *) (AP + _intsizeof (t))-_intsizeof (t))
After Va_arg () is replaced, the AP points to the next type of address after the T type. The va_arg itself is replaced by the value of the corresponding parameter of type T. The T type is generally converted from the FMT format string according to the%d,%c.
such as 1:int a = Va_art (AP, int);
such as 2:fun (int n,...)
{
...
char* pchar = Va_arg (AP, char*)
int TMP = VA_ARG (AP, int)
Double DD = Va_arg (AP, double)
}
So... Must be the char*,int,double order of the parameters. If this is not the order, the program will not crash periodically. It's
is why C is not type-safe, Boost::format seems to provide type-safe format conversions that can replace the use of sprintf.
For sprintf (), the value of Va_arg (av,v) v is extracted using the char* FMT.
Report:
3)//Example code 2: extension-a function that implements simple variable parameters on its own. (no va_list for macros)
Here is an implementation of a simple printf function, referring to the example in <the C programming language>
#include "stdio.h"
#include "Stdlib.h"
void myprintf (char* fmt, ...) A simple implementation similar to printf,//The argument must be of type int
{
char* Parg=null; Equivalent to the original va_list
char c;
PARG = (char*) &fmt; Be careful not to write P = fmt!! Because you want to address the//parameter here, not the value
PARG + + sizeof (FMT); Equivalent to the original Va_start
Todo
{
c =*fmt;
if (c!= '% ')
{
Putchar (c); Output characters as-is
}
Else
{
Output data by format character
Switch (*++FMT)
{
Case ' d ':
printf ("%d", * ((int*) parg));
Break
Case ' x ':
printf ("% #x", * ((int*) parg));
Break
Default
Break
}
Parg + = sizeof (int); Equivalent to the original va_arg
}
++FMT;
}while (*fmt!= '/0 ');
PARG = NULL; Equivalent to Va_end
Return
}
int main (int argc, char* argv[])
{
int i = 1234;
int j = 5678;
myprintf ("The test:i=%d/n", i,j);
myprintf ("The Secend test:i=%d; %x;j=%d;/n ", i,0xabcd,j);
System ("pause");
return 0;
}