8

我正在树莓派上编写一些串行代码并切换到 C99。当我这样做时,我开始收到错误“错误:'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 \

使用 -M 显示 2 个 termios.h 标头。前者不包含 CRTSCTS 的定义,而后者包含。

我假设标准 c89 使用的是好的 c99 而不是 c99,但我不确定,因为 -M 调用的结果是相同的。谁能向我解释为什么当我切换到 C99 时会发生这种情况以及如何解决它?

4

3 回答 3

6

-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
于 2014-12-08T08:41:29.480 回答
3

根据 xtreye 的要求,并且由于官方答案确实解释了但实际上并没有明确列出解决方案 - 我们都通过使用-std=gnu99编译器标志解决了这个问题。

希望有帮助。

于 2015-01-20T16:37:53.787 回答
1

至少在 gentoo 中,您可以使用-D_DEFAULT_SOURCE -std=c99代替。-std=gnu99对我来说,它“似乎更标准”。

在 中搜索/usr/include,我看到:

/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

其他文件,例如 in/usr/include/boost/*/usr/include/eigen3/*也使用_DEFAULT_SOURCE.

此外,@CamW 在评论中提供的链接非常有启发性:

   *  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
于 2022-01-12T00:35:25.703 回答