⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protomac.20000601.html

📁 this is a mirrored site c-faq. thought might need offline
💻 HTML
字号:
<html><!-- Mirrored from c-faq.com/style/protomac.20000601.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 08:02:16 GMT --><head><title></title></head><body><p>[Someone asked me the questionwhich is now 17.4b in the comp.lang.c FAQ list,and this was my reply.]<p>From: scs@eskimo.com (Steve Summit)<br>Subject: Re: A ``C'' Question<br>Date: Thu, 1 Jun 2000 11:43:30 -0700 (PDT)<br>Message-Id: &lt;200006011843.LAA29337@mail.eskimo.com&gt;<p>You wrote:<br>&gt; I have a ``C'' programming question. On UNIX system, in /usr/include <br>&gt; directory, there is a ctype.h.<p>As a general rule, you have to be careful when inspectingcompiler-supplied header files, for example the ones in/usr/include.  Often these make use of ``magic'' features which arenot standard and sometimes not even intended for users to use.This question, however, has a reasonably straightforward answer,and it's not tied to any particular compiler.<p>&gt; In this file, there is a prototype definition<br>&gt;        <TT>extern int isalpha __((int))</TT>.<br>&gt; I can not understand &lt;space&gt;<TT>__((int))</TT>. What is meaning of that?<br>&gt; My guess is that it is an argument to the function isalpha but<br>&gt; how come there is a space in between.<p>This is actually a trick.<p>As you may know, there are two kinds of external functionprototype declaration in C.  The old-fashioned kind looked like<p><pre>	extern int isalpha();</pre>and says that <TT>isalpha</TT> is a function returning <TT>int</TT>.  The newer,prototype form (which may be the only kind you're used to) lookslike<p><pre>	extern int isalpha(int);</pre>and supplies the additional information that the <TT>isalpha</TT> functionaccepts one argument, of type <TT>int</TT>.<p>Sometimes it's useful if a piece of code (in this case, a headerfile) can be compiled both by ANSI-compatible and pre-ANSIcompilers.  Function prototypes, however, were introduced alongwith the ANSI Standard.  Pre-ANSI compilers didn't understandfunction prototypes, and in fact a pre-ANSI compiler willgenerally report a ``syntax error'' when it sees a functionprototype.<p>The first half of the trick, therefore, is to make the presenceof the function prototype conditional.  Suppose we had the macro<p><pre>	#define PROTOTYPE(args) args</pre>This is a fairly useless-looking macro; all it does is accept onemacro argument and spit it back out.  But suppose we were towrite the prototype for isalpha as<p><pre>	extern int isalpha PROTOTYPE((int));</pre>After the preprocessor expanded the macro, we'd end up with<p><pre>	extern int isalpha (int);</pre>which is just like our original prototype (except for theinsertion of an extra space, which doesn't matter).<p>(One additional question here is why we have to invoke themacro as <TT>PROTOTYPE((int))</TT>, with an extra set of parentheses.The reason is so that the preprocessor won't complain when weuse the <TT>PROTOTYPE</TT> macro to help us declare a function that takesmultiple arguments.  If we invoked <TT>PROTOTYPE(int, double)</TT>, thepreprocessor would complain that we'd invoked the <TT>PROTOTYPE</TT> macrowith two macro arguments, while it expected only one.  But whenwe invoke it as <TT>PROTOTYPE((int, double))</TT>, as far as thepreprocessor is concerned we're invoking it with one argument,which is ``<TT>(int, double)</TT>'', including one pair of parentheses.)<p>Now, however, we have a way to ``turn off'' the prototype.  If weredefine the <TT>PROTOTYPE</TT> macro as<pre>	#define PROTOTYPE(args) ()</pre>the macro-ized declaration for isalpha would turn into<pre>	extern int isalpha ();</pre>and this would be acceptable to a pre-ANSI compiler.  So, puttingthis all together, we might say<p><pre>	#ifdef __STDC__	#define PROTOTYPE(args) args	#else	#define PROTOTYPE(args) ()	#endif	extern int isalpha PROTOTYPE((int));</pre><p>Now we have one scrap of code that's ``backwards compatible''to a pre-ANSI compiler.  (Obviously we only have to do the<TT>#ifdef</TT>/<TT>#define</TT>/<TT>#else</TT> thing once, then we can use the <TT>PROTOTYPE</TT>macro in lots of external function prototype declarations.)<p>The only problem with this is that<pre>	extern int isalpha PROTOTYPE((int));</pre>looks pretty ugly, due to that macro name <TT>PROTOTYPE</TT> sitting inthere.  Someone decided that it was worth trying to fix this.<p>The rule for identifiers in C is that they may consist ofletters, digits, and underscore characters, and that the firstcharacter must not be a digit.  This means that the firstcharacter <em>can</em> be an underscore.  But it also means thatidentifiers consisting of <em>only</em> underscores are legal!  Using asingle or a double underscore as an identifier is a pretty sneakytrick, and we obviously can't use it too often, but if we'vedecided that writing backwards-compatible function declarationswithout that ugly <TT>PROTOTYPE</TT> name is so important that we'rewilling to devote this sneaky trick to the task, we can replacethe macro name ``<TT>PROTOTYPE''</TT> with the macro name ``<TT>__</TT>'', leading to:<p><pre>	#ifdef __STDC__	#define __(args) args	#else	#define __(args) ()	#endif	extern int isalpha __((int));</pre><p>So that explains what you saw.  (Personally, I don't think thisis all worth it, and I don't use this trick, myself, but I'veseen it in plenty of code written by others.)<p><address><a href="http://www.eskimo.com/~scs/">Steve Summit</a><br><a href="mailto:scs@eskimo.com">scs@eskimo.com</a></address><br>-- <br>Programming Challenge #6: Don't just fix the bug.<br>See <a href="http://www.eskimo.com/~scs/challenge/">http://www.eskimo.com/~scs/challenge/</a>.</body><!-- Mirrored from c-faq.com/style/protomac.20000601.html by HTTrack Website Copier/3.x [XR&CO'2008], Sat, 14 Mar 2009 08:02:16 GMT --></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -