C language interface and implementation experiment -- Use of Variable Parameter tables (va_list, va_start, va_arg, va_end)

Source: Internet
Author: User

As an interface library, the C language interface and implementation uses variable parameter tables in a large number of source files. How do I use these parameters? Let's take a look at these examples and understand the use of variable parameter tables. The following sections describe the principles from the Internet:

SourceProgram:

# Include <stdio. h> # include <stdarg. h> # include <string. h> //// Example 1: append string // void va_fn1 (char * DEST, char * data ,...) {va_list AP; char * P = data; // point to the first variable parameter // The second parameter is written... previous va_start (AP, data); // traverses every variable parameter and uses while (1) {// to access the variable parameter. Use it first, and then traverse it !! Strcat (DEST, P); P = va_arg (AP, char *); If (P = NULL) break;} // end va_end (AP );} //// Example 2: Accumulate and // int va_fn2 (int ,...) {int ret = A; // point to the first parameter int sum = 0; va_list AP; // The second parameter is written... previous va_start (AP, a); // traverses each variable parameter and uses while (1) {// first, and then sums + = ret; ret = va_arg (AP, INT); If (ret =-1) break;} // end va_end (AP); Return sum ;}/// Example 3: use the data structure // typedef struct {int X; int y;} my_type; void va_fn3 (int n, my_type * P ,...) {int I = 0; va_list AP; my_type * TMP = P; // The second parameter is written... previous va_start (AP, P); For (; I <n; I ++) {printf ("\ t % d ----- % d \ n", TMP-> X, TMP-> Y); TMP = va_arg (AP, my_type *);} // end va_end (AP);} // Example 4: slightly complicated variable parameter table // (char *, Int, INT), (char *, Int, INT ),...... // void va_fn4 (char * MSG ,...) {va_list AP; int I, j; char * STR = MSG; // point to the first parameter // The second parameter is written... the previous va_start (AP, MSG); While (1) {// use a variable parameter table, first use I = va_arg (AP, INT); j = va_arg (AP, INT ); printf ("\ t % s --- % D ---- % d \ n", STR, I, j); // traverse STR = va_arg (AP, char *); // The second parameter is the variable parameter type if (STR = NULL) break;} // end va_end (AP);} void main () {// Example 1 char Dest [1000] = {0}; va_fn1 (DEST, "hello", "OK", "welcome", "yes", null ); printf ("Example 1 = % s \ n", DEST); // example 2int x = va_fn2 (9, 9, 1, 3, 90,-1 ); printf ("Example 2 = % d \ n", x); // example 3my_type A, B, C;. X = 100;. y = 300; B. X = 1100; B. y = 1300; C. X = 6100; C. y = 6300; printf ("Example 3: \ n"); va_fn3 (3, & A, & B, & C); // Example 4 printf ("Example 4: \ n "); va_fn4 (" hello ", 1, 2," XYZ ", 300,600," ABC ", 77, 88, null );}

Output:

 
Example 1 = Hello OK Welcome Yes Example 2 = 112 Example 3: 100-----300 1100-----1300 6100-----6300 Example 4: Hello --- 1----2 XYZ---300----600 ABC---77 ---- 88 press any key to continue

Principle:

1. function parameters are accessed in the form of a Data Structure: Stack, from right to left

2. First, the parameter memory storage format: the parameter is stored in the stack segment of the memory, and the function is executed from the last one to the stack. Therefore, the stack bottom high address and stack Top Low address are as follows:

Void func (int x, float y, charz );
Then, when calling the function, the real parameter char Z is first stack, then float y, and finally intx. Therefore, in the memory, the variable storage order is X-> Y-> Z, therefore, theoretically, we can find other input variables simply by detecting the address of any variable and knowing the type of other variables. <---- This is the principle !!

3. Check the source code (vc98/include/stdarg. h): (Note that it is x86 related, not MIPS, not Alpha, not PPC, and so on !)

Typedef char * va_list;

# Ifdef _ m_ix86

# DEFINE _ intsizeof (N) (sizeof (n) + sizeof (INT)-1 )&~ (Sizeof (INT)-1 ))

# Define va_start (AP, V) (AP = (va_list) & V + _ intsizeof (v ))
# Define va_arg (AP, t) (* (T *) (AP + = _ intsizeof (t)-_ intsizeof (t )))
# Define va_end (AP) (AP = (va_list) 0)

# Elif defined (_ m_mrx000)

There is a complex macro here. Expand it: manually enter/P in "Project Properties"> "C/C ++"> "project options", and then rebuild will be generated. CPP with the same name. the macro in the I file is expanded. Let's look at the first function after expansion:

 
Void va_fn1 (char * DEST, char * data ,...) {va_list AP; char * P = data; (AP = (va_list) & Data + (sizeof (data) + sizeof (INT)-1 )&~ (Sizeof (INT)-1); While (1) {strcat (DEST, P); P = (* (char **) (AP + = (sizeof (char *) + sizeof (INT)-1 )&~ (Sizeof (INT)-1)-(sizeof (char *) + sizeof (INT)-1 )&~ (Sizeof (INT)-1); If (P = 0) break;} (AP = (va_list) 0 );}

Let's look at the second function, which is simpler:

 int va_fn2 (int ,...) {int ret = A; int sum = 0; va_list AP; (AP = (va_list) & A + (sizeof (A) + sizeof (INT)-1 )&~ (Sizeof (INT)-1); While (1) {sum + = ret; ret = (* (int *) (AP + = (sizeof (INT) + sizeof (INT)-1 )&~ (Sizeof (INT)-1)-(sizeof (INT) + sizeof (INT)-1 )&~ (Sizeof (INT)-1); If (ret =-1) break;} (AP = (va_list) 0); Return sum;} 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.