Variable long parameter list error and trap--va_arg unacceptable type __c

Source: Internet
Author: User
Tags function prototype
Error of variable long parameter list and trap--va_arg an unacceptable type implements a variable long parameter list function and uses the macros provided in Stdarg.h (not discussed here Varargs.h).

For example, we want to implement a simple my_printf:
1. It only returns void and does not record the number of characters in the output
2. It only accepts "%d" by the integer output, "%c" by character output, "%" output '% ' itself
As follows:
1 #include < stdarg.h >
2
3 void my_printf (const char * fmt, ...)
4 {
5 va_list AP;
6 Va_start (AP,FMT); /* Initializes the AP with the last parameter type argument
7 for (; * FMT; + + FMT)
8 {
9/* If not the control character * *
if (* fmt!= '% ')
11 {
Putchar (* fmt); /* Direct OUTPUT * *
Continue;
14}
15/* If the control character, view the next character * *
+ + FMT;
if (' ==* ' fmt)/* If it is Terminator * *
18 {
ASSERT (0); * * This is a mistake * *
break;
21}
Switch (* fmt)
23 {
Case '% ':/* 2 consecutive '% ' Output 1 '% ' *
Putchar ('% ');
-Break;
Case ' d ':/* In accordance with INT output * *
28 {
29/* The next parameter is int, take out */
int i = Va_arg (AP, int);
To printf ("%d", I);
32}
The break;
Case ' C ':/* According to the character output * *
35 {
36 * * But the next parameter is char?
37/* Can be taken out like this. */
char c = Va_arg (AP, Char);
-printf ("%c", c);
40}
a break;
43}
44}
Va_end (AP); /* Releaseap-- must be. See RELATED LINKS*/
46}

This is similar to an exercise in the C + + programming language.
--Need to support the "%c" control character

In the C + + programming language-solution, an answer is given (Chinese p65 page).
But just like the code above, they are ErrorOf




To put it simply, when we use Va_arg (AP, type) to take out a parameter,
type must never be aThe following types:
—— Char, signed Char, unsigned Char
—— Short, unsigned Short
--signed Short Shortint, signed Shortint, unsigned ShortInt
—— float


One simple reason is:
—— The caller will neverTo my_printf passingThe above types of actual Parameters


In C, when you call a function without a prototype declaration:
The caller will eachParameter execution "default actual parameter Promotion(Default argument Promotions)”。

Also, for variable-length argument lists beyond the last oneYes formal arguments for type declarationsAfter the each actual parameter, the above promotion will also be performed.
The promotion work is as follows:
The actual parameters of the--float type are raised to double
Actual parameters for--char, short, and corresponding signed, unsigned types are elevated to int
--If int cannot store the original value, it is promoted to unsigned int

The caller will then after AscensionThe parameters passingto the callee.
So, my_printf is absolutely no way to receiveThe actual parameters of the type above.



The 38 and 39 lines of the above code should read:
int c = Va_arg (AP, int);
printf ("%c", c);
Similarly, if you need to use short and float, you should do the same:
Short s = (short) Va_arg (AP, int);
float f = (float) Va_arg (AP, Double);
This is also why the printf family function does not have a control character for short and float.


Appendix:

This pitfall is not mentioned in the relevant chapters of the C programming language for variable-length parameter lists.
But there are rules that refer to the default actual parameter elevation:

In the absence of a function prototype, both the char and the short type are converted to the int type, and the float type is converted to the double type.
--"C Language Programming" 2nd Edition 2.7 type conversion p36



In other books, there are also references to this rule:


It is clear that if a parameter is not declared, the compiler will have no information to perform a standard type check and conversion on it.
In this case, a char or short will be passed as int, and float will be passed as a double.
These do not have to be the programmer's expectation.
Footnotes: These are the standard improvements that are inherited by the C language.
For arguments represented by ellipses, their actual parameters perform these ascension (if they belong to a type that requires elevation) before passing, passing the promoted value to the related function. --Translator's note
--"C + + programming language" 3rd Edition-Special Edition 7.6 p138

.... The parameters of the float type are automatically converted to the double type, and the parameters of the short or char type are automatically converted to the int type ...
--"C Traps and defects" 4.4 formal parameters, real participation return value p73


Here's a trap to avoid:
The 2nd parameter of the VA_ARG macro cannot be specified as Char ShortOr floatType.
Because parameters for char and short types are converted to the int type, the parameters of the float type are converted to double types ...
For example, write this It's definitely not right .Of
c = Va_arg (Ap,char);
Because we cannot pass a char type parameter, if passed, it will be automatically converted to the int type. The formula above should be written:
c = Va_arg (Ap,int);
--"C Traps and defects" p164


2009/05/07 Modified:
The printf function family has a control character "H" for short.
See: http://www.cplusplus.com/reference/clibrary/cstdio/printf/


RELATED links:

--"Variable long parameter list misunderstanding and traps--va_end is necessary?" 》
Http://www.cppblog.com/ownwaterloo/archive/2009/04/21/is_va_end_necessary.html





This work is licensed with the knowledge sharing signature-non-commercial use-sharing 2.5 Chinese mainland license agreement in the same way.

Reprint Please specify:
Article Author-Ownwaterloo
Release date-April 21, 2009
Original link-http://www.cppblog.com/ownwaterloo/archive/2009/04/21/unacceptable_type_in_va_arg.html

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.