Next: Fixed Headers, Previous: Interoperation, Up: Trouble
There are several noteworthy incompatibilities between GNU C and K&R (non-ISO) versions of C.
One consequence is that you cannot call mktemp
with a string
constant argument. The function mktemp
always alters the
string its argument points to.
Another consequence is that sscanf
does not work on some very
old systems when passed a string constant as its format control string
or input. This is because sscanf
incorrectly tries to write
into the string constant. Likewise fscanf
and scanf
.
The solution to these problems is to change the program to use
char
-array variables with initialization strings for these
purposes instead of string constants.
-2147483648
is positive.
This is because 2147483648 cannot fit in the type int
, so
(following the ISO C rules) its data type is unsigned long int
.
Negating this value yields 2147483648 again.
#define foo(a) "a"
will produce output "a"
regardless of what the argument a is.
setjmp
and longjmp
, the only automatic
variables guaranteed to remain valid are those declared
volatile
. This is a consequence of automatic register
allocation. Consider this function:
jmp_buf j; foo () { int a, b; a = fun1 (); if (setjmp (j)) return a; a = fun2 (); /*longjmp (j)
may occur infun3
. */ return a + fun3 (); }
Here a
may or may not be restored to its first value when the
longjmp
occurs. If a
is allocated in a register, then
its first value is restored; otherwise, it keeps the last value stored
in it.
If you use the -W option with the -O option, you will get a warning when GCC thinks such a problem might be possible.
foobar ( #define luser hack)
ISO C does not permit such a construct.
In some other C compilers, an extern
declaration affects all the
rest of the file even if it happens within a block.
long
, etc., with a typedef name,
as shown here:
typedef int foo; typedef long foo bar;
In ISO C, this is not allowed: long
and other type modifiers
require an explicit int
.
typedef int foo; typedef foo foo;
#if 0 You can't expect this to work. #endif
The best solution to such a problem is to put the text into an actual C comment delimited by ‘/*...*/’.
time
, so it did not matter what type your program declared it to
return. But in systems with ISO C headers, time
is declared to
return time_t
, and if that is not the same as long
, then
‘long time ();’ is erroneous.
The solution is to change your program to use appropriate system headers
(<time.h>
on systems with ISO C headers) and not to declare
time
if the system header files declare it, or failing that to
use time_t
as the return type of time
.
float
, PCC converts it to
a double. GCC actually returns a float
. If you are concerned
with PCC compatibility, you should declare your functions to return
double
; you might as well say what you mean.
The method used by GCC is as follows: a structure or union which is
1, 2, 4 or 8 bytes long is returned like a scalar. A structure or union
with any other size is stored into an address supplied by the caller
(usually in a special, fixed register, but on some machines it is passed
on the stack). The target hook TARGET_STRUCT_VALUE_RTX
tells GCC where to pass this address.
By contrast, PCC on most target machines returns structures and unions of any size by copying the data into an area of static storage, and then returning the address of that storage as if it were a pointer value. The caller must copy the data from that memory area to the place where the value is wanted. GCC does not use this method because it is slower and nonreentrant.
On some newer machines, PCC uses a reentrant convention for all structure and union returning. GCC on most of these machines uses a compatible convention when returning structures and unions in memory, but still returns small structures and unions in registers.
You can tell GCC to use a compatible convention for all structure and union returning with the option -fpcc-struct-return.
A preprocessing token is a preprocessing number if it begins with a digit and is followed by letters, underscores, digits, periods and ‘e+’, ‘e-’, ‘E+’, ‘E-’, ‘p+’, ‘p-’, ‘P+’, or ‘P-’ character sequences. (In strict C90 mode, the sequences ‘p+’, ‘p-’, ‘P+’ and ‘P-’ cannot appear in preprocessing numbers.)
To make the above program fragment valid, place whitespace in front of the minus sign. This whitespace will end the preprocessing number.