C variable parameter functions

Source: Internet
Author: User

1. What are variable parameters?
In C language programming, we sometimes encounter some functions with variable parameter numbers, such as the printf () function. Its prototype is:
Int printf (const char * format ,...);
In addition to the fixed format parameter, the number and type of parameters following are variable (with three vertices "... "Parameter placeholder), the actual call can take the following form:
Printf ("% d", I );
Printf ("% s", S );
Printf ("the number is % d, string is: % s", I, S );
These are already familiar to everyone. However, the question of how to write variable parameters to C functions and how to implement these Variable Parameter Function compilers has been bothering me for a long time. This article will discuss this issue and hope to help you.

Ii. Processing of variable parameters in the Compiler
We know that va_start, va_arg, and va_end are in stdarg. H is defined as a macro. Because 1) the hardware platform is different, 2) the compiler is different, so the defined macro is also different. Let's take a look at stdarg in VC ++ 6.0. code in H (the file path is/vc98/include/stdarg under the VC installation directory. h)
Typedef char * va_list;
# 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)

The following describes the meaning of the Code:

1. First, we define va_list as char *, because on our current PC, the character pointer type can be used to store memory unit addresses. On some machines, va_list is defined as void *.

2. Define _ intsizeof (n) mainly for some systems that require memory alignment. This macro aims to get the actual memory size of the last fixed parameter. The sizeof operator is directly used on my machine, which has no impact on the running structure of the program. (I will see my own implementations later ).

3. va_start is defined as & V + _ intsizeof (V). Here & V is the starting address of the last fixed parameter, plus the actual occupied size, the starting memory address of the first variable parameter is obtained. So after we run va_start (AP, V), the AP points to the memory address of the first variable parameter. With this address, it will be easy in the future.

Here you need to know two things:
(1) On intel + Windows machines, the function stack is oriented down. The memory address of the stack top pointer is lower than the stack bottom pointer, therefore, the data of the advanced stack is stored in the high address of the memory.
(2) among the vast majority of C compilers such as Vc, by default, the parameter stack-to-stack order is from right to left. Therefore, the memory model after the parameter stack is shown in: the address of the last fixed parameter is located under the first variable parameter and is continuously stored.
| -------------------------------- |
| Last variable parameter |-> high memory address
| -------------------------------- |
| -------------------------------- |
| Nth variable parameter |-> place indicated by arg_ptr after va_arg (arg_ptr, INT,
| The address of the nth variable parameter.
| ------------------------------- |
| -------------------------------- |
| First variable parameter |-> place indicated by arg_ptr after va_start (arg_ptr, start)
| Address of the first Variable Parameter
| -------------------------------- |
| ------------------------------ -- |
|
| Last fixed parameter |-> Start address
| --------------------------------|

| -------------------------------- |
|
| -------------------------------- |-> Low memory address

(4) va_arg (): With the good foundation of va_start, we have obtained the address of the first variable parameter, in va_arg () the task in is to obtain the value of this parameter based on the specified parameter type, and adjust the pointer to the starting address of the next parameter.
Therefore, now let's look at the implementation of va_arg (). We should be aware of it:
# Define va_arg (AP, t) (* (T *) (AP + = _ intsizeof (t)-_ intsizeof (t )))
This macro has done two things,
① Use the type name entered by the user to forcibly convert the parameter address to obtain the value required by the user
② Calculate the actual size of this parameter, and adjust the pointer to the end of this parameter, that is, the first address of the next parameter, for later processing.

(5) interpretation of the va_end macro: The X86 platform is defined as AP = (char *) 0, so that the AP no longer points to the stack, but is the same as null. some are directly defined as (void *) 0, so that the compiler will not generate code for va_end. For example, GCC is defined in this way on the Linux X86 platform. you should pay attention to one problem: Because the address of the parameter is used in the va_start macro, the parameter cannot be declared as a register variable or as a function or array type. this is the description of va_start, va_arg, and va_end. We should note that different operating systems and hardware platforms have different definitions, but their principles are similar.

Iii. Notes for variable parameters in programming
Because va_start, va_arg, and va_end are defined as macros, it seems stupid. the types and numbers of variable parameters are completely controlled by the program code in this function, it cannot intelligently identify the number and type of different parameters. someone may ask: Isn't Intelligent Recognition parameters implemented in printf? That is because the function printf analyzes the parameter type from the fixed parameter format string, and then calls va_arg to obtain variable parameters. that is to say, if you want to implement Intelligent Identification of variable parameters, you must make judgments in your own programs. for example, a possible implementation of printf is provided in section 7.3 of the C's typical textbook the C programming language.

Iv. Summary:
1. The three Macros in the Standard C library are used only to determine the memory address of each parameter in the Variable Parameter List. The Compiler does not know the actual number of parameters.
2. in actual application code, the programmer must determine the number of parameters, as shown in figure
(1) This method is used to set the flag-printf function in fixed parameters. An example is provided later.
(2) set a special end mark in advance, that is, to input a variable parameter. when calling the variable parameter, set the value of the last variable parameter to this special value, in the function body, determine whether the parameter end is reached based on this value. The code above this article adopts this method.
No matter which method is used, programmers should tell the caller their conventions in the document.
3. The key to variable parameters is to find a way to get the address of each parameter. The method to get the address is determined by the following factors:
① Function stack growth direction
② Input stack order of parameters
③ CPU alignment
④ Memory address expression
Combined with the source code, we can see that the implementation of va_list is determined by ④, and the introduction of _ intsizeof (n) is determined by ③, he and ① (2) jointly determine the implementation of va_start. Finally, the existence of va_end is a reflection of a good programming style, and the pointer that is no longer used is set to null, which can prevent future misoperations.
4. After obtaining the address and combining the parameter type, the programmer can process the parameter correctly. After understanding the above points, I believe that readers with a little experience can write implementations suitable for their own machines.

From: http://blog.csdn.net/zhoujunyi/archive/2007/04/19/1570835.aspx

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.