📄 autobook_51.html
字号:
va_list ap; char *arg; va_start (ap); ... arg = va_arg (ap, char *); ... va_end (ap); return arg ? strlen (arg) : 0;}</pre></td></tr></table></P><P>ANSI C provides a similar API, imported with <SAMP>`#include<stdarg.h>'</SAMP>, though it cannot express a variadic function with no namedarguments such as the one above. In practice, this isn't a problemsince you always need at least one parameter, either to specify thetotal number of arguments somehow, or else to mark the end of theargument list. An ANSI variadic function definition looks likethis:</P><P><TABLE width=100%><tr><td> </td><td class=example bgcolor=#6688aa><br><pre>intfunctionname (char *format, ...){ va_list ap; char *arg; va_start (ap, format); ... arg = va_arg (ap, char *); ... va_end (ap); return format ? strlen (format) : 0;}</pre></td></tr></table></OL><P>Except in very rare cases where you are writing a low level project(GCC for example), you probably don't need to worry about K&Rcompilers too much. However, supporting them can be very easy, and ifyou are so inclined, can be handled either by employing the<CODE>ansi2knr</CODE> program supplied with Automake, or by careful use ofthe preprocessor.</P><P>Using <CODE>ansi2knr</CODE> in your project is described in some detail insection `Automatic de-ANSI-fication' in <CITE>The Automake Manual</CITE>, butboils down to the following:</P><P><UL><LI>Add this macro to your <TT>`configure.in'</TT> file:<P><TABLE width=100%><tr><td> </td><td class=example bgcolor=#6688aa><br><pre>AM_C_PROTOTYPES</pre></td></tr></table></P><P><LI>Rewrite the contents of <SAMP>`LIBOBJS'</SAMP> and/or <SAMP>`LTLIBOBJS'</SAMP> inthe following fashion:<P><TABLE width=100%><tr><td> </td><td class=example bgcolor=#6688aa><br><pre># This is necessary so that .o files in LIBOBJS are also built via# the ANSI2KNR-filtering rules.Xsed='sed -e "s/^X//"'LIBOBJS=`echo X"$LIBOBJS"|\ [$Xsed -e 's/\.[^.]* /.\$U& /g;s/\.[^.]*$/.\$U&/']`</pre></td></tr></table></UL><P>Personally, I dislike this method, since every source file is filteredand rewritten with ANSI function prototypes and declarationsconverted to K&R style adding a fair overhead in additional files inyour build tree, and in compilation time. This would be reasonable werethe abstraction sufficient to allow you to forget about K&R entirely,but <CODE>ansi2knr</CODE> is a simple program, and does not address any ofthe other differences between compilers that I raised above, and itcannot handle macros in your function prototypes of definitions. If youdecide to use <CODE>ansi2knr</CODE> in your project, you must make thedecision before you write any code, and be aware of its limitations asyou develop.</P><P>For my own projects, I prefer to use a set of preprocessor macros alongwith a few stylistic conventions so that all of the differences betweenK&R and ANSI compilers are actually addressed, and so that theunfortunate few who have no access to an ANSI compiler (and whocannot use GCC for some reason) needn't suffer the overheads of<CODE>ansi2knr</CODE>.</P><P>The four differences in style listed at the beginning of this subsectionare addressed as follows:</P><P><OL><LI>The function prototype argument lists are declared inside a <CODE>PARAMS</CODE>macro invocation so that K&R compilers will still be able to compile thesource tree. <CODE>PARAMS</CODE> removes ANSI argument lists fromfunction prototypes for <FONT SIZE="-1">K&R</FONT> compilers. Some developerscontinue to use <CODE>__P</CODE> for this purpose, but strictly speaking,macros starting with <SAMP>`_'</SAMP> (and especially <SAMP>`__'</SAMP>) are reservedfor the compiler and the system headers, so using <SAMP>`PARAMS'</SAMP>, asfollows, is safer:<P><TABLE width=100%><tr><td> </td><td class=example bgcolor=#6688aa><br><pre>#if __STDC__# ifndef NOPROTOS# define PARAMS(args) args# endif#endif#ifndef PARAMS# define PARAMS(args) ()#endif</pre></td></tr></table></P><P>This macro is then used for all function declarations like this:</P><P><TABLE width=100%><tr><td> </td><td class=example bgcolor=#6688aa><br><pre>extern int functionname PARAMS((const char *parameter));</pre></td></tr></table></P><P><LI>With the <CODE>PARAMS</CODE> macro is used for all function declarations,ANSI compilers are given all the type information they require todo full compile time type checking. The function definitionsproper must then be declared in K&R style so that K&R compilers don'tchoke on ANSI syntax. There is a small amount of overhead inwriting code this way, however: The ANSI compile time typechecking can only work in conjunction with K&R function definitions ifit first sees an ANSI function prototype. This forces you todevelop the good habit of prototyping <EM>every single</EM> function inyour project. Even the <CODE>static</CODE> ones.<P><LI>The easiest way to work around the lack of <CODE>void *</CODE> pointers, is todefine a new type that is conditionally set to <CODE>void *</CODE> forANSI compilers, or <CODE>char *</CODE> for <FONT SIZE="-1">K&R</FONT> compilers. Youshould add the following to a common header file:<P><TABLE width=100%><tr><td> </td><td class=example bgcolor=#6688aa><br><pre>#if __STDC__typedef void *void_ptr;#else /* !__STDC__ */typedef char *void_ptr;#endif /* __STDC__ */</pre></td></tr></table></P><P><LI>The difference between the two variadic function APIs pose astickier problem, and the solution is ugly. But it <EM>does</EM> work.First you must check for the headers in <TT>`configure.in'</TT>:<P><TABLE width=100%><tr><td> </td><td class=example bgcolor=#6688aa><br><pre>AC_CHECK_HEADERS(stdarg.h varargs.h, break)</pre></td></tr></table></P><P>Having done this, add the following code to a common header file:</P><P><TABLE width=100%><tr><td> </td><td class=example bgcolor=#6688aa><br><pre>#if HAVE_STDARG_H# include <stdarg.h># define VA_START(a, f) va_start(a, f)#else# if HAVE_VARARGS_H# include <varargs.h># define VA_START(a, f) va_start(a)# endif#endif#ifndef VA_START error no variadic api#endif</pre></td></tr></table></P><P>You must now supply each variadic function with both a K&R and anANSI definition, like this:</P><P><TABLE width=100%><tr><td> </td><td class=example bgcolor=#6688aa><br><pre>int#if HAVE_STDARG_Hfunctionname (const char *format, ...)#elsefunctionname (format, va_alist) const char *format; va_dcl#endif{ va_alist ap; char *arg; VA_START (ap, format); ... arg = va_arg (ap, char *); ... va_end (ap); return arg : strlen (arg) ? 0;}</pre></td></tr></table></OL><P><A NAME="A Simple Shell Builders Library"></A></TR></TABLE><BR> <FONT SIZE="-1">This document was generatedby <I>Gary V. Vaughan</I> on <I>September, 12 2004</I>using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html"><I>texi2html</I></A></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -