【问题标题】:How to check if uint8_t exists as a type, instead of unsigned char?如何检查 uint8_t 是否作为类型存在,而不是 unsigned char?
【发布时间】:2013-08-08 16:17:24
【问题描述】:

我有两个编译器,一个可以识别 uint8_t(GCC ARM-EABI),一个不识别(Renesas M16 Standard Toolchain)。

瑞萨工具链不符合 ANSI C,因此您可以丢弃 .所以 uint8_t, uint16_t,... 没有被定义为现有类型。

为了保持可移植性,我希望有相同的类型(最好是uint8_t,由于int的歧义)。

我的平台也是不同大小的处理器(ARM 是 32 位,瑞萨是 16 位)。导致 int 为不同的值。

有没有办法检查 uint8_t 是否作为类型存在?

如果不是,将其(以及其他 uint16_t、uint32_t、...)声明为类型?

【问题讨论】:

  • 瑞萨工具链中是否存在uint_least8_t
  • std::is_same<unsigned char, uint8_t>::value.
  • 制作一个包含 的头文件,如果当前编译器是 Renesas 则定义这些类型,否则什么都不做。
  • 我认为 uint_least8_t 不存在

标签: c++ c embedded


【解决方案1】:

有没有办法检查 uint8_t 是否作为类型存在?

用途:

#include <stdint.h>

#ifdef UINT8_MAX
...
#endif

【讨论】:

  • 建议扩展此正确答案以处理 OP 的第二个问题“如果不是,请将其 (...) 声明为类型?”
  • 原来我的编译器真的很烂。没有 stdint.h 文件。
【解决方案2】:

uint8_t 不是内置类型,它在 stdint.h 中定义。所以这不是编译器“识别” uint8_t 的问题,而只是使 stdint.h 可用的一个案例。

如果您的工具链不提供 stdint.h,您可以轻松地提供自己的实现,使用编译器文档来确定与特定大小相对应的内置类型。在没有 stdint.h 的工具链上,您只需向项目提供您自己的工具链,在带有 stdint.h 的工具链上您不需要。这样代码(除了 stdint.h 本身)将在不同平台上是相同的 - 您不需要有条件地定义 uint8_t。

您可能遇到的一个问题(例如在某些 TI DSP 上)是内存可能不是 8 位可寻址的,而 char 将是 16 位(或更大)。在这种情况下,uint8_t 或任何 8 位整数类型将根本不受支持。 char 始终是特定平台的最小数据类型,但可能大于 8 位。

【讨论】:

  • 支持 8 位,但 stdint.h 无法识别。
  • @Ashitakalax:那就做一个吧。您可能只需要实现基本类型的子集来编译大多数代码,但您也可以编写一个完全符合 ISO C99 的实现,其中包含完整的专业类型和宏:refHere's an example implementation for VC++ 6,当然是 32 位的,但是你只需要改变几个 typedef 来适应 16 位的目标。
  • 是的,我打算制作一个特定于该设备的文件。我只是不确定在没有额外文件的情况下是否有简单的方法。
  • @Ashitakalax:有什么比做一次然后在之后的所有项目中使用它更容易的了。
【解决方案3】:

有几种不同的方法可以解决这个问题。在需要可移植的开源项目中,常见的解决方案是拥有一个“配置脚本”,运行该脚本来设置构建系统。然后它会在某些config.h 或类似的[这是“配置脚本”的结果之一中设置或未设置HAVE_UINTX_TYPES 之类的东西,并执行以下操作:

#include "config.h"
...
#ifndef HAVE_UINTX_TYPES
#include "uintx_types.h"
#endif

在“几乎不需要在任何东西上运行”的系统中,您可以通过简单地将-DHAVE_UINTX_TYPES 作为编译器标志的一部分来解决相同的问题。并且由于您(可能)有构建系统的某些部分设置不同的编译选项,选择不同的编译器等,因此对于两个不同的构建,这应该不是一个大问题。

假设您很高兴您的 unsigned char 确实是 8 位,那么您也可以拥有一个包含以下内容的 uintx_types.h

typedef unsigned char  uint8_t; 
typedef unsigned short uint16_t;
typedef unsigned long  uint32_t; 

另一种选择是不直接使用uint8_tuint16_t 等,而是有自己的定义[并且这些定义取决于“是ARM 还是瑞萨”的适当构建设置,例如通过使用不同的包含选项]:

ARM/types.h:

typedef unsigned char  u_int8;
typedef unsigned short u_int16;
typedef unsigned int   u_int32;

瑞萨/types.h:

typedef unsigned char  u_int8;
typedef unsigned int   u_int16;
typedef unsigned long  u_int32;

【讨论】:

  • 看到我的平台不支持 uintN_t 我将不得不实施某种检测。配置脚本不是想法,尽管构建系统存在巨大差异,并且有自己的内置编译器。但是我可以添加一个小头文件来为瑞萨声明这些类型。 Gwah 该死的愚蠢编译器。
  • @Ashitakalax:平台支持无关紧要——这些类型是在头文件中定义的,你可以创建任何你想要的头文件,如果你碰巧称它为 stdint.h,那么你所有的代码将独立于平台工具链。 stdint.h 中的 nothing 无法使用 C89 编译器实现。
  • @Ashitakalax:我同意 Clifford 的观点 - 如果编译器没有 stdint.h 标头,那么自己制作,这是一个很好的解决方案。
【解决方案4】:

如果uint8_t不存在,要么是因为实现不符合C99,要么是因为它没有满足要求的类型。后者可能意味着CHAR_BIT &gt; 8(在嵌入式系统之外非常罕见)。

#if __STDC_VERSION__ >= 199901L
#include <stdint.h>
#ifdef UINT8_MAX
// uint8_t exists
#else
// uint8_t doesn't exist in <stdint.h>
#else
// uint8_t probably doesn't exist because this isn't a C99 or better compiler
#endif

不完全符合 C99 的实现可以提供 &lt;stdint.h&gt;uint8_t 作为扩展。这很难检测,因为没有条件 #include 指令; #include 要么包含请求的标头,要么失败。

但是你可以通过在 C 语言之外使用某种配置脚本来检测它。如果编译:

#include <stdint.h>
uint8_t dummy;

那么uint8_t 存在;否则不会。

【讨论】:

    【解决方案5】:

    uint8_t 的主要观点是它不会存在于不支持正好为 8 位的无符号整数类型的平台上。如果unsigned char 是可接受的,即使它可能大于8 位,那么不要使用uint8_t。在一个平台上使用 unsigned char 而在另一个平台上使用 uint8_t 没有任何好处。

    【讨论】:

    • 它也不存在于随机平台上,因为某些任意其他原因根本没有实现它 - 尽管它的存在表明它适用于该架构,但不存在并不能证明处理器不支持 8 位。
    • 不存在证明实现不符合 C 标准或 CHAR_BIT 大于 8。
    • @R.. 或实现符合 C89
    • 我的平台支持 8 位无符号字符,但不支持 uint8_t。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 2013-04-01
    • 2013-09-01
    • 2011-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多