gcc: Incompatibilities
1
1 13.3 Incompatibilities of GCC
1 =============================
1
1 There are several noteworthy incompatibilities between GNU C and K&R
1 (non-ISO) versions of C.
1
1 * GCC normally makes string constants read-only. If several
1 identical-looking string constants are used, GCC stores only one
1 copy of the string.
1
1 One consequence is that you cannot call 'mktemp' with a string
1 constant argument. The function 'mktemp' always alters the string
1 its argument points to.
1
1 Another consequence is that 'sscanf' does not work on some very old
1 systems when passed a string constant as its format control string
1 or input. This is because 'sscanf' incorrectly tries to write into
1 the string constant. Likewise 'fscanf' and 'scanf'.
1
1 The solution to these problems is to change the program to use
1 'char'-array variables with initialization strings for these
1 purposes instead of string constants.
1
1 * '-2147483648' is positive.
1
1 This is because 2147483648 cannot fit in the type 'int', so
1 (following the ISO C rules) its data type is 'unsigned long int'.
1 Negating this value yields 2147483648 again.
1
1 * GCC does not substitute macro arguments when they appear inside of
1 string constants. For example, the following macro in GCC
1
1 #define foo(a) "a"
1
1 will produce output '"a"' regardless of what the argument A is.
1
1 * When you use 'setjmp' and 'longjmp', the only automatic variables
1 guaranteed to remain valid are those declared 'volatile'. This is
1 a consequence of automatic register allocation. Consider this
1 function:
1
1 jmp_buf j;
1
1 foo ()
1 {
1 int a, b;
1
1 a = fun1 ();
1 if (setjmp (j))
1 return a;
1
1 a = fun2 ();
1 /* 'longjmp (j)' may occur in 'fun3'. */
1 return a + fun3 ();
1 }
1
1 Here 'a' may or may not be restored to its first value when the
1 'longjmp' occurs. If 'a' is allocated in a register, then its
1 first value is restored; otherwise, it keeps the last value stored
1 in it.
1
1 If you use the '-W' option with the '-O' option, you will get a
1 warning when GCC thinks such a problem might be possible.
1
1 * Programs that use preprocessing directives in the middle of macro
1 arguments do not work with GCC. For example, a program like this
1 will not work:
1
1 foobar (
1 #define luser
1 hack)
1
1 ISO C does not permit such a construct.
1
1 * K&R compilers allow comments to cross over an inclusion boundary
1 (i.e. started in an include file and ended in the including file).
1
1 * Declarations of external variables and functions within a block
1 apply only to the block containing the declaration. In other
1 words, they have the same scope as any other declaration in the
1 same place.
1
1 In some other C compilers, an 'extern' declaration affects all the
1 rest of the file even if it happens within a block.
1
1 * In traditional C, you can combine 'long', etc., with a typedef
1 name, as shown here:
1
1 typedef int foo;
1 typedef long foo bar;
1
1 In ISO C, this is not allowed: 'long' and other type modifiers
1 require an explicit 'int'.
1
1 * PCC allows typedef names to be used as function parameters.
1
1 * Traditional C allows the following erroneous pair of declarations
1 to appear together in a given scope:
1
1 typedef int foo;
1 typedef foo foo;
1
1 * GCC treats all characters of identifiers as significant. According
1 to K&R-1 (2.2), "No more than the first eight characters are
1 significant, although more may be used.". Also according to K&R-1
1 (2.2), "An identifier is a sequence of letters and digits; the
1 first character must be a letter. The underscore _ counts as a
1 letter.", but GCC also allows dollar signs in identifiers.
1
1 * PCC allows whitespace in the middle of compound assignment
1 operators such as '+='. GCC, following the ISO standard, does not
1 allow this.
1
1 * GCC complains about unterminated character constants inside of
1 preprocessing conditionals that fail. Some programs have English
1 comments enclosed in conditionals that are guaranteed to fail; if
1 these comments contain apostrophes, GCC will probably report an
1 error. For example, this code would produce an error:
1
1 #if 0
1 You can't expect this to work.
1 #endif
1
1 The best solution to such a problem is to put the text into an
1 actual C comment delimited by '/*...*/'.
1
1 * Many user programs contain the declaration 'long time ();'. In the
1 past, the system header files on many systems did not actually
1 declare 'time', so it did not matter what type your program
1 declared it to return. But in systems with ISO C headers, 'time'
1 is declared to return 'time_t', and if that is not the same as
1 'long', then 'long time ();' is erroneous.
1
1 The solution is to change your program to use appropriate system
1 headers ('<time.h>' on systems with ISO C headers) and not to
1 declare 'time' if the system header files declare it, or failing
1 that to use 'time_t' as the return type of 'time'.
1
1 * When compiling functions that return 'float', PCC converts it to a
1 double. GCC actually returns a 'float'. If you are concerned with
1 PCC compatibility, you should declare your functions to return
1 'double'; you might as well say what you mean.
1
1 * When compiling functions that return structures or unions, GCC
1 output code normally uses a method different from that used on most
1 versions of Unix. As a result, code compiled with GCC cannot call
1 a structure-returning function compiled with PCC, and vice versa.
1
1 The method used by GCC is as follows: a structure or union which is
1 1, 2, 4 or 8 bytes long is returned like a scalar. A structure or
1 union with any other size is stored into an address supplied by the
1 caller (usually in a special, fixed register, but on some machines
1 it is passed on the stack). The target hook
1 'TARGET_STRUCT_VALUE_RTX' tells GCC where to pass this address.
1
1 By contrast, PCC on most target machines returns structures and
1 unions of any size by copying the data into an area of static
1 storage, and then returning the address of that storage as if it
1 were a pointer value. The caller must copy the data from that
1 memory area to the place where the value is wanted. GCC does not
1 use this method because it is slower and nonreentrant.
1
1 On some newer machines, PCC uses a reentrant convention for all
1 structure and union returning. GCC on most of these machines uses
1 a compatible convention when returning structures and unions in
1 memory, but still returns small structures and unions in registers.
1
1 You can tell GCC to use a compatible convention for all structure
1 and union returning with the option '-fpcc-struct-return'.
1
1 * GCC complains about program fragments such as '0x74ae-0x4000' which
1 appear to be two hexadecimal constants separated by the minus
1 operator. Actually, this string is a single "preprocessing token".
1 Each such token must correspond to one token in C. Since this does
1 not, GCC prints an error message. Although it may appear obvious
1 that what is meant is an operator and two values, the ISO C
1 standard specifically requires that this be treated as erroneous.
1
1 A "preprocessing token" is a "preprocessing number" if it begins
1 with a digit and is followed by letters, underscores, digits,
1 periods and 'e+', 'e-', 'E+', 'E-', 'p+', 'p-', 'P+', or 'P-'
1 character sequences. (In strict C90 mode, the sequences 'p+',
1 'p-', 'P+' and 'P-' cannot appear in preprocessing numbers.)
1
1 To make the above program fragment valid, place whitespace in front
1 of the minus sign. This whitespace will end the preprocessing
1 number.
1