【问题标题】:CRTSCTS not define when compiling as C99编译为 C99 时未定义 CRTSCTS
【发布时间】:2015-01-12 16:25:15
【问题描述】:

我正在树莓派上编写一些串行代码并切换到 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,但我不确定,因为 -M 调用的结果是相同的。谁能向我解释为什么当我切换到 C99 时会发生这种情况以及如何解决它?

【问题讨论】:

  • 感谢 Mat,用 -std=gnu99 编译器标志修复了它。
  • '-std=gnu99' 也给我打了个电话,您可以将其发布为答案

标签: c raspberry-pi c99 termios


【解决方案1】:

-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 \

在定义 __USE_MISC 时,在 bits/termios.h 中定义了 CRTSCTS

     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

而 _BSD_SOURCE 和 _SVID_SOURCE 是在定义 _GNU_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

【讨论】:

  • gnu99 是 ISO C99 带有 GNU 扩展。虽然它可能不会对 Raspberry Pi 造成大问题,但您冒着无法生成可移植代码的风险。
【解决方案2】:

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

希望对您有所帮助。

【讨论】:

    【解决方案3】:

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

    /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 在评论中提供的link 很有启发性:

       *  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
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 2011-01-08
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    相关资源
    最近更新 更多