CRTSCTS not define when compiling as C99

6.2k views Asked by At

I'm writing some serial code on a raspberry pi and switched to C99. When I did I started getting the error "error: ‘CRTSCTS’ undeclared (first use in this function)"

$ c99 -M serial01.c | grep termios.h
 /usr/include/termios.h /usr/include/arm-linux-gnueabihf/bits/termios.h \
$ gcc -M serial01.c | grep termios.h
 /usr/include/termios.h /usr/include/arm-linux-gnueabihf/bits/termios.h \

using -M reveals 2 termios.h headers. the former does not contain a definition for CRTSCTS and the latter does.

I assume the standard c89 is using the good one and c99 not but I'm not sure since the result of the -M call is identical. Can anyone explain to me why this is happening when I switch to C99 and how to fix it?

3

There are 3 answers

1
honzakuzel1989 On BEST ANSWER

-std=gnu99 is the solution. More detailed below.

Result of the gcc/c99 -M call is identical but it does not mean anything! The explanation of this behavior are preprocessor macros (specifically GNU extensions, like said Mat).

In detail:

cat -n main.c
     1  #include <termios.h>
     2
     3  int printf(const char *, ...);
     4
     5  int main(void)
     6  {
     7      printf("%d\n", CRTSCTS);
     8      return 0;
     9  }
gcc main.c -o main --std=c89 -> 'CRTSCTS' undeclared compilation error
gcc main.c -o main --std=cgnu89 -> successfully compiled

This behavior is the same for c99 and gnu99!

Like said Cameron, -M output is identical:

gcc -M --std=c89 main.c | grep termios.h | nl
     1  main.o: main.c /usr/include/termios.h /usr/include/features.h \
     2   /usr/include/arm-linux-gnueabihf/bits/termios.h
gcc -M --std=gnu89 main.c | grep termios.h | nl
1  main.o: main.c /usr/include/termios.h /usr/include/features.h \
     2   /usr/include/arm-linux-gnueabihf/bits/termios.h \

CRTSCTS is defined in the bits/termios.h when __USE_MISC is defined

     1  #ifdef __USE_MISC
     2  # define CIBAUD   002003600000          /* input baud rate (not used) */
     3  # define CMSPAR   010000000000          /* mark or space (stick) parity */
     4  # define CRTSCTS  020000000000          /* flow control */

Let's look at __USE_MISC.

gcc -M /usr/include/termios.h | nl
     1  termios.o: /usr/include/termios.h /usr/include/features.h \
     2   /usr/include/arm-linux-gnueabihf/bits/predefs.h \
     3   /usr/include/arm-linux-gnueabihf/sys/cdefs.h \
     4   /usr/include/arm-linux-gnueabihf/bits/wordsize.h \
     5   /usr/include/arm-linux-gnueabihf/gnu/stubs.h \
     6   /usr/include/arm-linux-gnueabihf/bits/types.h \
     7   /usr/include/arm-linux-gnueabihf/bits/typesizes.h \
     8   /usr/include/arm-linux-gnueabihf/bits/termios.h \
     9   /usr/include/arm-linux-gnueabihf/sys/ttydefaults.h

First one, features.h, contains definition of __USE_MISC, but only when _BSD_SOURCE or _SVID_SOURCE is defined

grep 'define __USE_MISC' /usr/include/features.h -B 1 | nl
     1  #if defined _BSD_SOURCE || defined _SVID_SOURCE
     2  # define __USE_MISC     1

and _BSD_SOURCE and _SVID_SOURCE is defined when _GNU_SOURCE or 'nothing' is defined

     1  #ifdef _GNU_SOURCE
     2  # undef  _ISOC95_SOURCE
     3  # define _ISOC95_SOURCE 1
     4  # undef  _ISOC99_SOURCE
     5  # define _ISOC99_SOURCE 1
     6  # undef  _POSIX_SOURCE
     7  # define _POSIX_SOURCE  1
     8  # undef  _POSIX_C_SOURCE
     9  # define _POSIX_C_SOURCE        200809L
    10  # undef  _XOPEN_SOURCE
    11  # define _XOPEN_SOURCE  700
    12  # undef  _XOPEN_SOURCE_EXTENDED
    13  # define _XOPEN_SOURCE_EXTENDED 1
    14  # undef  _LARGEFILE64_SOURCE
    15  # define _LARGEFILE64_SOURCE    1
    16  # undef  _BSD_SOURCE
    17  # define _BSD_SOURCE    1
    18  # undef  _SVID_SOURCE
    19  # define _SVID_SOURCE   1
    20  # undef  _ATFILE_SOURCE
    21  # define _ATFILE_SOURCE 1
    22  #endif

    23  /* If nothing (other than _GNU_SOURCE) is defined,
    24     define _BSD_SOURCE and _SVID_SOURCE.  */
    25  #if (!defined __STRICT_ANSI__ && !defined _ISOC99_SOURCE && \
    26       !defined _POSIX_SOURCE && !defined _POSIX_C_SOURCE && \
    27       !defined _XOPEN_SOURCE && !defined _BSD_SOURCE && !defined _SVID_SOURCE)
    28  # define _BSD_SOURCE    1
    29  # define _SVID_SOURCE   1
    30  #endif
0
CamW On

As requested by xtreye and since the official answer does explain but doesn't actually explicitly list the solution - We both fixed this by using a -std=gnu99 compiler flag.

Hope that helps.

1
vesperto On

You can use -D_DEFAULT_SOURCE -std=c99 instead of -std=gnu99, at least in gentoo. It "seems more standard" to me.

Searching around in /usr/include, I see:

/usr/include/features.h

 52    _DEFAULT_SOURCE  The default set of features (taking precedence over
 53       __STRICT_ANSI__).
 
 61    The `-ansi' switch to the GNU C compiler, and standards conformance
 62    options such as `-std=c99', define __STRICT_ANSI__.  If none of
 63    these are defined, or if _DEFAULT_SOURCE is defined, the default is
 64    to have _POSIX_SOURCE set to one and _POSIX_C_SOURCE set to
 65    200809L, as well as enabling miscellaneous functions from BSD and
 66    SVID.  If more than one of these are defined, they accumulate.  For
 67    example __STRICT_ANSI__, _POSIX_SOURCE and _POSIX_C_SOURCE together
 68    give you ISO C, 1003.1, and 1003.2, but nothing else.
 
383 #if defined _DEFAULT_SOURCE
384 # define __USE_MISC 1
385 #endif

Other files, such as in /usr/include/boost/* and /usr/include/eigen3/* also make use of _DEFAULT_SOURCE.

Also, the link provided by @CamW in a comment is quite enlightening:

   *  The macros that you most likely need to use in modern source
      code are _POSIX_C_SOURCE (for definitions from various
      versions of POSIX.1), _XOPEN_SOURCE (for definitions from
      various versions of SUS), _GNU_SOURCE (for GNU and/or Linux
      specific stuff), and _DEFAULT_SOURCE (to get definitions that
      would normally be provided by default).

   _DEFAULT_SOURCE (since glibc 2.19)
          This macro can be defined to ensure that the "default"
          definitions are provided even when the defaults would
          otherwise be disabled, as happens when individual macros
          are explicitly defined, or the compiler is invoked in one
          of its "standard" modes (e.g., cc -std=c99).  Defining
          _DEFAULT_SOURCE without defining other individual macros
          or invoking the compiler in one of its "standard" modes
          has no effect.

          The "default" definitions comprise those required by
          POSIX.1-2008 and ISO C99, as well as various definitions
          originally derived from BSD and System V.  On glibc 2.19
          and earlier, these defaults were approximately equivalent
          to explicitly defining the following:

              cc -D_BSD_SOURCE -D_SVID_SOURCE
          -D_POSIX_C_SOURCE=200809