1 Copyright (C) 2000, 2003 Free Software Foundation, Inc.
3 This file is intended to contain a few notes about writing C code
4 within GCC so that it compiles without error on the full range of
5 compilers GCC needs to be able to compile on.
7 The problem is that many ISO-standard constructs are not accepted by
8 either old or buggy compilers, and we keep getting bitten by them.
9 This knowledge until know has been sparsely spread around, so I
10 thought I'd collect it in one useful place. Please add and correct
11 any problems as you come across them.
13 I'm going to start from a base of the ISO C89 standard, since that is
14 probably what most people code to naturally. Obviously using
15 constructs introduced after that is not a good idea.
17 The first section of this file deals strictly with portability issues,
18 the second with common coding pitfalls, and the third with obsolete
19 K+R portability issues.
28 Some SGI compilers choke on the parentheses in:-
30 const char string[] = ("A string");
32 This is unfortunate since this is what the GNU gettext macro N_
33 produces. You need to find a different way to code it.
35 Some compilers like MSVC++ have fairly low limits on the maximum
36 length of a string literal; 509 is the lowest we've come across. You
37 may need to break up a long printf statement into many smaller ones.
43 ISO C (6.8.3 in the 1990 standard) specifies the following:
45 If (before argument substitution) any argument consists of no
46 preprocessing tokens, the behavior is undefined.
48 This was relaxed by ISO C99, but some older compilers emit an error,
54 needs to be coded in some other way.
60 Some implementations crash upon attempts to free or realloc the null
61 pointer. Thus if mem might be null, you need to write
70 You weren't going to use them anyway, but some otherwise ISO C
71 compliant compilers do not accept trigraphs.
74 Suffixes on Integer Constants
75 -----------------------------
77 You should never use a 'l' suffix on integer constants ('L' is fine),
78 since it can easily be confused with the number '1'.
81 Common Coding Pitfalls
82 ======================
87 errno might be declared as a macro.
93 In C, the 'int' keyword can often be omitted from type declarations.
94 For instance, you can write
100 unsigned int variable;
102 There are several places where this can cause trouble. First, suppose
103 'variable' is a long; then you might think
107 would convert it to unsigned long. It does not. It converts to
108 unsigned int. This mostly causes problems on 64-bit platforms, where
109 long and int are not the same size.
111 Second, if you write a function definition with no return type at
114 operate (int a, int b)
119 that function is expected to return int, *not* void. GCC will warn
122 Implicit function declarations always have return type int. So if you
123 correct the above definition to
126 operate (int a, int b)
129 but operate() is called above its definition, you will get an error
130 about a "type mismatch with previous implicit declaration". The cure
131 is to prototype all functions at the top of the file, or in an
134 Char vs unsigned char vs int
135 ----------------------------
137 In C, unqualified 'char' may be either signed or unsigned; it is the
138 implementation's choice. When you are processing 7-bit ASCII, it does
139 not matter. But when your program must handle arbitrary binary data,
140 or fully 8-bit character sets, you have a problem. The most obvious
141 issue is if you have a look-up table indexed by characters.
143 For instance, the character '\341' in ISO Latin 1 is SMALL LETTER A
144 WITH ACUTE ACCENT. In the proper locale, isalpha('\341') will be
145 true. But if you read '\341' from a file and store it in a plain
146 char, isalpha(c) may look up character 225, or it may look up
147 character -31. And the ctype table has no entry at offset -31, so
148 your program will crash. (If you're lucky.)
150 It is wise to use unsigned char everywhere you possibly can. This
151 avoids all these problems. Unfortunately, the routines in <string.h>
152 take plain char arguments, so you have to remember to cast them back
153 and forth - or avoid the use of strxxx() functions, which is probably
156 Another common mistake is to use either char or unsigned char to
157 receive the result of getc() or related stdio functions. They may
158 return EOF, which is outside the range of values representable by
159 char. If you use char, some legal character value may be confused
160 with EOF, such as '\377' (SMALL LETTER Y WITH UMLAUT, in Latin-1).
161 The correct choice is int.
163 A more subtle version of the same mistake might look like this:
165 unsigned char pushback[NPUSHBACK];
167 #define unget(c) (assert(pbidx < NPUSHBACK), pushback[pbidx++] = (c))
168 #define get(c) (pbidx ? pushback[--pbidx] : getchar())
172 which will mysteriously turn a pushed-back EOF into a SMALL LETTER Y
176 Other common pitfalls
177 ---------------------
179 o Expecting 'plain' char to be either sign or unsigned extending
181 o Shifting an item by a negative amount or by greater than or equal to
182 the number of bits in a type (expecting shifts by 32 to be sensible
183 has caused quite a number of bugs at least in the early days).
185 o Expecting ints shifted right to be sign extended.
187 o Modifying the same value twice within one sequence point.
189 o Host vs. target floating point representation, including emitting NaNs
190 and Infinities in a form that the assembler handles.
192 o qsort being an unstable sort function (unstable in the sense that
193 multiple items that sort the same may be sorted in different orders
194 by different qsort functions).
196 o Passing incorrect types to fprintf and friends.
198 o Adding a function declaration for a module declared in another file to
199 a .c file instead of to a .h file.
202 K+R Portability Issues
203 ======================
208 K+R C compilers and preprocessors have no notion of unary '+'. Thus
209 the following code snippet contained 2 portability problems.
211 int x = +2; /* int x = 2; */
219 K+R C compilers did not have a void pointer, and used char * as the
220 pointer to anything. The macro PTR is defined as either void * or
221 char * depending on whether you have a standards compliant compiler or
224 free ((void *) h->value.expansion);
226 should have been written
228 free ((PTR) h->value.expansion);
230 Further, an initial investigation indicates that pointers to functions
231 returning void were okay. Thus the example given by "Calling
232 functions through pointers to functions" below appeared not to cause a
239 K+R C did not allow concatenation of string literals like
241 "This is a " "single string literal".
247 The signed keyword did not exist in K+R compilers; it was introduced
248 in ISO C89, so you could not use it. In both K+R and standard C,
249 unqualified char and bitfields may be signed or unsigned. There is no
250 way to portably declare signed chars or signed bitfields.
252 All other arithmetic types are signed unless you use the 'unsigned'
253 qualifier. For instance, it was safe to write
261 If you have an algorithm that depends on signed char or signed
262 bitfields, you had to find another way to write it before it could be
269 You need to provide a function prototype for every function before you
270 use it, and functions had to be defined K+R style. The function
271 prototype should have used the PARAMS macro, which takes a single
272 argument. Therefore the parameter list had to be enclosed in
273 parentheses. For example,
275 int myfunc PARAMS ((double, int *));
285 This implies that if the function takes no arguments, it had to be
286 declared and defined as follows:
288 int myfunc PARAMS ((void));
296 You also had to use PARAMS when referring to function protypes in
297 other circumstances, for example see "Calling functions through
298 pointers to functions" below.
300 Variable-argument functions are best described by example:-
302 void cpp_ice PARAMS ((cpp_reader *, const char *msgid, ...));
305 cpp_ice VPARAMS ((cpp_reader *pfile, const char *msgid, ...))
308 VA_FIXEDARG (ap, cpp_reader *, pfile);
309 VA_FIXEDARG (ap, const char *, msgid);
315 See ansidecl.h for the definitions of the above macros and more.
317 One aspect of using K+R style function declarations, is you could not
318 have arguments whose types are char, short, or float, since without
319 prototypes (ie, K+R rules), these types are promoted to int, int, and
322 Calling functions through pointers to functions
323 -----------------------------------------------
325 K+R C compilers require parentheses around the dereferenced function
326 pointer expression in the call, whereas ISO C relaxes the syntax. For
329 typedef void (* cl_directive_handler) PARAMS ((cpp_reader *, const char *));
330 *p->handler (pfile, p->arg);
334 (*p->handler) (pfile, p->arg);
340 The rules under K+R C and ISO C for achieving stringification and
341 token pasting are quite different. Therefore some macros have been
342 defined which will get it right depending upon the compiler.
344 CONCAT2(a,b) CONCAT3(a,b,c) and CONCAT4(a,b,c,d)
346 will paste the tokens passed as arguments. You must not leave any
347 space around the commas. Also,
351 will stringify an argument; to get the same result on K+R and ISO
352 compilers x should not have spaces around it.
355 Passing structures by value
356 ---------------------------
358 You had to avoid passing structures by value, either to or from
359 functions. It seems some K+R compilers handle this differently or not
366 In K+R C, you had to cast enum types to use them as integers, and some
367 compilers in particular give lots of warnings for using an enum as an
374 See also "signed keyword" above. In K+R C only unsigned int bitfields
375 were defined (i.e. unsigned char, unsigned short, unsigned long.
376 Using plain int/short/long was not allowed).
382 K+R C has "entry" as a reserved keyword, so you had to not use it for
389 K+R used unsigned-preserving rules for arithmetic expresssions, while
390 ISO uses value-preserving. This means an unsigned char compared to an
391 int is done as an unsigned comparison in K+R (since unsigned char
392 promotes to unsigned) while it is signed in ISO (since all of the
393 values in unsigned char fit in an int, it promotes to int).
396 Suffixes on Integer Constants
397 -----------------------------
399 K+R C did not accept a 'u' suffix on integer constants. If you wanted
400 to declare a constant to be be unsigned, you had to use an explicit