Deleted Added
full compact
README.Portability (117395) README.Portability (132718)
1Copyright (C) 2000 Free Software Foundation, Inc.
1Copyright (C) 2000, 2003 Free Software Foundation, Inc.
2
3This file is intended to contain a few notes about writing C code
4within GCC so that it compiles without error on the full range of
5compilers GCC needs to be able to compile on.
6
7The problem is that many ISO-standard constructs are not accepted by
8either old or buggy compilers, and we keep getting bitten by them.
9This knowledge until know has been sparsely spread around, so I
10thought I'd collect it in one useful place. Please add and correct
11any problems as you come across them.
12
2
3This file is intended to contain a few notes about writing C code
4within GCC so that it compiles without error on the full range of
5compilers GCC needs to be able to compile on.
6
7The problem is that many ISO-standard constructs are not accepted by
8either old or buggy compilers, and we keep getting bitten by them.
9This knowledge until know has been sparsely spread around, so I
10thought I'd collect it in one useful place. Please add and correct
11any problems as you come across them.
12
13I'm going to start from a base of the ISO C89 standard, since that is
13I'm going to start from a base of the ISO C90 standard, since that is
14probably what most people code to naturally. Obviously using
15constructs introduced after that is not a good idea.
16
14probably what most people code to naturally. Obviously using
15constructs introduced after that is not a good idea.
16
17The first section of this file deals strictly with portability issues,
18the second with common coding pitfalls.
17For the complete coding style conventions used in GCC, please read
18http://gcc.gnu.org/codingconventions.html
19
20
19
20
21 Portability Issues
22 ==================
23
24Unary +
25-------
26
27K+R C compilers and preprocessors have no notion of unary '+'. Thus
28the following code snippet contains 2 portability problems.
29
30int x = +2; /* int x = 2; */
31#if +1 /* #if 1 */
32#endif
33
34
35Pointers to void
36----------------
37
38K+R C compilers did not have a void pointer, and used char * as the
39pointer to anything. The macro PTR is defined as either void * or
40char * depending on whether you have a standards compliant compiler or
41a K+R one. Thus
42
43 free ((void *) h->value.expansion);
44
45should be written
46
47 free ((PTR) h->value.expansion);
48
49Further, an initial investigation indicates that pointers to functions
50returning void are okay. Thus the example given by "Calling functions
51through pointers to functions" below appears not to cause a problem.
52
53
54String literals
55---------------
56
21String literals
22---------------
23
57Some SGI compilers choke on the parentheses in:-
24Irix6 "cc -n32" and OSF4 "cc" have problems with constant string
25initializers with parens around it, e.g.
58
59const char string[] = ("A string");
60
61This is unfortunate since this is what the GNU gettext macro N_
62produces. You need to find a different way to code it.
63
26
27const char string[] = ("A string");
28
29This is unfortunate since this is what the GNU gettext macro N_
30produces. You need to find a different way to code it.
31
64K+R C did not allow concatenation of string literals like
32Some compilers like MSVC++ have fairly low limits on the maximum
33length of a string literal; 509 is the lowest we've come across. You
34may need to break up a long printf statement into many smaller ones.
65
35
66 "This is a " "single string literal".
67
36
68Moreover, some compilers like MSVC++ have fairly low limits on the
69maximum length of a string literal; 509 is the lowest we've come
70across. You may need to break up a long printf statement into many
71smaller ones.
72
73
74Empty macro arguments
75---------------------
76
77ISO C (6.8.3 in the 1990 standard) specifies the following:
78
79If (before argument substitution) any argument consists of no
80preprocessing tokens, the behavior is undefined.
81
82This was relaxed by ISO C99, but some older compilers emit an error,
83so code like
84
85#define foo(x, y) x y
86foo (bar, )
87
88needs to be coded in some other way.
89
90
37Empty macro arguments
38---------------------
39
40ISO C (6.8.3 in the 1990 standard) specifies the following:
41
42If (before argument substitution) any argument consists of no
43preprocessing tokens, the behavior is undefined.
44
45This was relaxed by ISO C99, but some older compilers emit an error,
46so code like
47
48#define foo(x, y) x y
49foo (bar, )
50
51needs to be coded in some other way.
52
53
91signed keyword
92--------------
93
94The signed keyword did not exist in K+R compilers; it was introduced
95in ISO C89, so you cannot use it. In both K+R and standard C,
96unqualified char and bitfields may be signed or unsigned. There is no
97way to portably declare signed chars or signed bitfields.
98
99All other arithmetic types are signed unless you use the 'unsigned'
100qualifier. For instance, it is safe to write
101
102 short paramc;
103
104instead of
105
106 signed short paramc;
107
108If you have an algorithm that depends on signed char or signed
109bitfields, you must find another way to write it before it can be
110integrated into GCC.
111
112
113Function prototypes
114-------------------
115
116You need to provide a function prototype for every function before you
117use it, and functions must be defined K+R style. The function
118prototype should use the PARAMS macro, which takes a single argument.
119Therefore the parameter list must be enclosed in parentheses. For
120example,
121
122int myfunc PARAMS ((double, int *));
123
124int
125myfunc (var1, var2)
126 double var1;
127 int *var2;
128{
129 ...
130}
131
132This implies that if the function takes no arguments, it should be
133declared and defined as follows:
134
135int myfunc PARAMS ((void));
136
137int
138myfunc ()
139{
140 ...
141}
142
143You also need to use PARAMS when referring to function protypes in
144other circumstances, for example see "Calling functions through
145pointers to functions" below.
146
147Variable-argument functions are best described by example:-
148
149void cpp_ice PARAMS ((cpp_reader *, const char *msgid, ...));
150
151void
152cpp_ice VPARAMS ((cpp_reader *pfile, const char *msgid, ...))
153{
154 VA_OPEN (ap, msgid);
155 VA_FIXEDARG (ap, cpp_reader *, pfile);
156 VA_FIXEDARG (ap, const char *, msgid);
157
158 ...
159 VA_CLOSE (ap);
160}
161
162See ansidecl.h for the definitions of the above macros and more.
163
164One aspect of using K+R style function declarations, is you cannot
165have arguments whose types are char, short, or float, since without
166prototypes (ie, K+R rules), these types are promoted to int, int, and
167double respectively.
168
169Calling functions through pointers to functions
170-----------------------------------------------
171
172K+R C compilers require parentheses around the dereferenced function
173pointer expression in the call, whereas ISO C relaxes the syntax. For
174example
175
176typedef void (* cl_directive_handler) PARAMS ((cpp_reader *, const char *));
177 *p->handler (pfile, p->arg);
178
179needs to become
180
181 (*p->handler) (pfile, p->arg);
182
183
184Macros
185------
186
187The rules under K+R C and ISO C for achieving stringification and
188token pasting are quite different. Therefore some macros have been
189defined which will get it right depending upon the compiler.
190
191 CONCAT2(a,b) CONCAT3(a,b,c) and CONCAT4(a,b,c,d)
192
193will paste the tokens passed as arguments. You must not leave any
194space around the commas. Also,
195
196 STRINGX(x)
197
198will stringify an argument; to get the same result on K+R and ISO
199compilers x should not have spaces around it.
200
201
202Passing structures by value
203---------------------------
204
205Avoid passing structures by value, either to or from functions. It
206seems some K+R compilers handle this differently or not at all.
207
208
209Enums
210-----
211
212In K+R C, you have to cast enum types to use them as integers, and
213some compilers in particular give lots of warnings for using an enum
214as an array index.
215
216
217Bitfields
218---------
219
220See also "signed keyword" above. In K+R C only unsigned int bitfields
221were defined (i.e. unsigned char, unsigned short, unsigned long.
222Using plain int/short/long was not allowed).
223
224
225free and realloc
226----------------
227
228Some implementations crash upon attempts to free or realloc the null
229pointer. Thus if mem might be null, you need to write
230
231 if (mem)
232 free (mem);
233
234
54free and realloc
55----------------
56
57Some implementations crash upon attempts to free or realloc the null
58pointer. Thus if mem might be null, you need to write
59
60 if (mem)
61 free (mem);
62
63
235Reserved Keywords
236-----------------
237
238K+R C has "entry" as a reserved keyword, so you should not use it for
239your variable names.
240
241
242Type promotions
243---------------
244
245K+R used unsigned-preserving rules for arithmetic expresssions, while
246ISO uses value-preserving. This means an unsigned char compared to an
247int is done as an unsigned comparison in K+R (since unsigned char
248promotes to unsigned) while it is signed in ISO (since all of the
249values in unsigned char fit in an int, it promotes to int).
250
251Trigraphs
252---------
253
64Trigraphs
65---------
66
254You weren't going to use them anyway, but trigraphs were not defined
255in K+R C, and some otherwise ISO C compliant compilers do not accept
256them.
67You weren't going to use them anyway, but some otherwise ISO C
68compliant compilers do not accept trigraphs.
257
258
259Suffixes on Integer Constants
260-----------------------------
261
69
70
71Suffixes on Integer Constants
72-----------------------------
73
262K+R C did not accept a 'u' suffix on integer constants. If you want
263to declare a constant to be be unsigned, you must use an explicit
264cast.
265
266You should never use a 'l' suffix on integer constants ('L' is fine),
267since it can easily be confused with the number '1'.
268
269
270 Common Coding Pitfalls
271 ======================
272
273errno

--- 21 unchanged lines hidden (view full) ---

295
296would convert it to unsigned long. It does not. It converts to
297unsigned int. This mostly causes problems on 64-bit platforms, where
298long and int are not the same size.
299
300Second, if you write a function definition with no return type at
301all:
302
74You should never use a 'l' suffix on integer constants ('L' is fine),
75since it can easily be confused with the number '1'.
76
77
78 Common Coding Pitfalls
79 ======================
80
81errno

--- 21 unchanged lines hidden (view full) ---

103
104would convert it to unsigned long. It does not. It converts to
105unsigned int. This mostly causes problems on 64-bit platforms, where
106long and int are not the same size.
107
108Second, if you write a function definition with no return type at
109all:
110
303 operate (a, b)
304 int a, b;
111 operate (int a, int b)
305 {
306 ...
307 }
308
309that function is expected to return int, *not* void. GCC will warn
112 {
113 ...
114 }
115
116that function is expected to return int, *not* void. GCC will warn
310about this. K+R C has no problem with 'void' as a return type, so you
311need not worry about that.
117about this.
312
313Implicit function declarations always have return type int. So if you
314correct the above definition to
315
316 void
118
119Implicit function declarations always have return type int. So if you
120correct the above definition to
121
122 void
317 operate (a, b)
318 int a, b;
123 operate (int a, int b)
319 ...
320
321but operate() is called above its definition, you will get an error
322about a "type mismatch with previous implicit declaration". The cure
323is to prototype all functions at the top of the file, or in an
324appropriate header.
325
326Char vs unsigned char vs int

--- 36 unchanged lines hidden (view full) ---

363
364which will mysteriously turn a pushed-back EOF into a SMALL LETTER Y
365WITH UMLAUT.
366
367
368Other common pitfalls
369---------------------
370
124 ...
125
126but operate() is called above its definition, you will get an error
127about a "type mismatch with previous implicit declaration". The cure
128is to prototype all functions at the top of the file, or in an
129appropriate header.
130
131Char vs unsigned char vs int

--- 36 unchanged lines hidden (view full) ---

168
169which will mysteriously turn a pushed-back EOF into a SMALL LETTER Y
170WITH UMLAUT.
171
172
173Other common pitfalls
174---------------------
175
371o Expecting 'plain' char to be either sign or unsigned extending
176o Expecting 'plain' char to be either sign or unsigned extending.
372
373o Shifting an item by a negative amount or by greater than or equal to
374 the number of bits in a type (expecting shifts by 32 to be sensible
375 has caused quite a number of bugs at least in the early days).
376
377o Expecting ints shifted right to be sign extended.
378
379o Modifying the same value twice within one sequence point.

--- 4 unchanged lines hidden (view full) ---

384o qsort being an unstable sort function (unstable in the sense that
385 multiple items that sort the same may be sorted in different orders
386 by different qsort functions).
387
388o Passing incorrect types to fprintf and friends.
389
390o Adding a function declaration for a module declared in another file to
391 a .c file instead of to a .h file.
177
178o Shifting an item by a negative amount or by greater than or equal to
179 the number of bits in a type (expecting shifts by 32 to be sensible
180 has caused quite a number of bugs at least in the early days).
181
182o Expecting ints shifted right to be sign extended.
183
184o Modifying the same value twice within one sequence point.

--- 4 unchanged lines hidden (view full) ---

189o qsort being an unstable sort function (unstable in the sense that
190 multiple items that sort the same may be sorted in different orders
191 by different qsort functions).
192
193o Passing incorrect types to fprintf and friends.
194
195o Adding a function declaration for a module declared in another file to
196 a .c file instead of to a .h file.
197