Variable parameters of water drop stone wearing C language

xiaoxiao2021-03-06  17

Overview

C language has a length uncertain parameter, such as "...", which is mainly used in a function of the number of parameters, and what we easily think is the PRINTF function.

prototype:

INT Printf (const char * format [, argument] ...);

Use example:

Printf ("Enjoy YourSelf Everyday! / N"); Printf ("THE VALUE IS% D! / N", Value);

This variable parameter can be said to be a C language a more difficult part, which will cause some of its analysis by several problems.

Note: There is a function overload in C can be used to distinguish between different function parameters, but it still does not represent any number of function parameters.

Question: Implementation of Printf

Excuse me, how to implement the Printf function, how to deal with the variable parameter problem? Answer and analysis:

A header file is defined in the standard C language specifically to deal with the variable parameter list, which contains a set of macros, and a VA_LIST's TypeDef declaration. A typical implementation is as follows:

Typedef char * va_list; #define va_start (list) list = (char *) & VA_ALIST # define v_end (list) #define va_arg (list, mode) / ((Mode *) (List = sizeof (Mode)) [ 1] Implement Printf: #include int printf (char * format, ...) {va_list ap; va_start (AP, format); int N = vprintf (format, AP); VA_END (AP); Return N }

Problem: The parameters determined when running

Is there a way to write a function, the specific form of this function parameter can determine when running?

Answer and analysis:

There is currently no solution to "formal" solution, but the unique remedies have one, because there is a function that has given us an example, which is main (), its prototype is:

INT Main (int Argc, char * argv []);

The parameters of the function are Argc and Argv.

Think in depth, "can only determine the parameters in runtime", that is, you can't see the parameters accepted from the statement, that is, the parameters are not fixed in the form. Common ways is that you can use it to point to the actual parameter area by defining a VOID * type, and then explain their meaning as needed in the function. This is the meaning of Argv in the main function, and ARGC is used to indicate the number of actual parameters, which provides us with further convenience, of course, this parameter is not required.

Although the parameters do not have a fixed form, we will inevitably analyze the meaning of parameters in the function, so there will be a requirement, which is the format, size, validity of the caller and the subject, etc. Danching, otherwise, all the words were miserable.

Problem: Transfer of variable length parameters

Sometimes, you need to write a function, pass it directly to another function. Can this require?

Answer and analysis:

At present, you have no way to do this directly, but we can go backwards. First, we define the parameters of the called function as the VA_List type, and convert the variable length parameter list to VA_LIST in the call function, so that you can do The transmission of the bearing parameters. See below: Void Subfunc (Char * FMT, VA_LIST Argp) {... arg = VA_ARG (FMT, Argp); / * Remove the parameters from ARGP * / ...}

Void Mainfunc (Char * fmt, ...) {va_list argp; va_start (argp, fmt); / * converts the variable length parameters to VA_LIST * / SUBFUNC (FMT, Argp); / * Pass VA_LIST to the child function * / VA_END (ARGP); ...}

Problem: The type of variable length parameter is a function pointer

I would like to use VA_ARG to extract the parameters of the type function pointer in the variable length parameter, but the result is always incorrect, why?

Answer and analysis:

This is related to the implementation of VA_ARG. A simple, the demonstration version of the VA_ARG implementation is as follows:

#define va_arg (argp, type) / (* ((argp) = sizeof (type)) - sizeof (Type)))

Among them, the type of Argp is char *.

If you want to extract the parameters of the function pointer type from the variable parameter list, for example

INT (*), then VA_ARG (argp, int (*)) is expanded to: (* (int (*) () *) ((argp) = sizeof (int (*)) ) -sizeof (int (*)))))))))

Obviously, (int (*) () *) is meaningless.

The way to solve this problem is to define the function pointer to define a separate data type, for example:

TYPEDEF INT (* Funcptr) ();

At this time, call VA_ARG (ARGP, FUNCPTR) will be expanded to:

(* (funcptr *) ((argp) = sizeof (funcptr)) - SIZEOF (FUNCPTR)))))

This can be checked by compilation.

Problem: Get the variable length parameters

There is a function with variable length parameters, where the following code is used to get the type of Float:

VA_ARG (Argp, Float);

may I handle it in this way?

Answer and analysis:

No. In variable length parameters, the application is "widened" principle. That is, the float type is expanded into Double; char, SHORT is extended into int. Therefore, if you want to go to the variable length parameter list, you need to use Va_arg (Argp, Double). Use VA_ARG (Argp, int) to the char and short types.

Problem: Define a limit for variable length parameters

Why is my compiler not allow me to define the following functions, that is, the variable length parameters, but there is no fixed parameter?

INT f (...) {...}

Answer and analysis:

No. This is requested by ANSI C, you can define a fixed parameter at least.

This parameter will be passed to VA_START (), and then use VA_ARG () and VA_END () to determine the type and value of the variable length parameters when the actual call is actually invoked.

转载请注明原文地址:https://www.9cbs.com/read-47078.html

New Post(0)