编译为C99时未定义CRTSCTS。

9

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

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

我认为标准c89使用了好的那一个,而c99则没有,但我不确定,因为-M调用的结果是相同的。有人可以解释一下当我切换到C99时为什么会发生这种情况以及如何解决吗?


1
谢谢Mat,我用-std=gnu99编译器标志修复了它。 - CamW
2
"-std=gnu99" 也困扰了我,你可以将其发布为答案。 - no id
3个回答

8

-std=gnu99就是解决方案。更详细的内容如下。

使用gcc/c99 -M调用的结果相同,但这并不意味着什么!这种行为的解释是预处理器宏(特别是GNU扩展,如Mat所说)。

详细情况如下:

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

这个行为在c99和gnu99中都是相同的! 就像卡梅隆所说,-M输出是相同的:
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 在定义 __USE_MISC 的情况下在 bits/termios.h 中被定义。
     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 */

让我们来看一下 __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

首先,features.h 文件包含 __USE_MISC 的定义,但仅当 _BSD_SOURCE 或 _SVID_SOURCE 被定义时才会生效。

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

当定义了_GNU_SOURCE或“nothing”时,_BSD_SOURCE和_SVID_SOURCE也被定义。
     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

1
gnu99 是带有 GNU 扩展的 ISO C99。虽然它可能不会在 Raspberry Pi 上引起大问题,但您冒着无法生成可移植代码的风险。 - vesperto

3

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

希望这有所帮助。


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

其他文件,例如在/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

1
有趣的是,基于这个答案,我发现了https://man7.org/linux/man-pages/man7/feature_test_macros.7.html,它非常清楚地解释了一切。 - CamW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接