【问题标题】:Is there a standard way to detect bit width of hardware?是否有检测硬件位宽的标准方法?
【发布时间】:2010-07-27 17:27:51
【问题描述】:

int 类型的变量据称是“一个机器类型的字长” 但是在嵌入式系统中,用于 8 位 micro 的 C 编译器使用 16 位的 int!,(对于 unsigned char 为 8 位)然后对于更多位,int 表现正常: 在 16 位 micros 中,int 也是 16 位,在 32 位 micros 中,int 是 32 位,等等。

那么,有没有一种标准的方法来测试它,比如 BITSIZEOF(int) ?

像“sizeof”是针对字节但针对位的。

这是我的第一个想法

    register c=1;                
    int bitwidth=0;
    do
    {

        bitwidth++;

    }while(c<<=1);

    printf("Register bit width is : %d",bitwidth);

但是它需要 c 作为 int,并且在 8 位编译器中使用 int 作为 16 位是很常见的,所以它给了我 16 作为结果,似乎没有使用“int”作为“寄存器宽度”的标准,(否则不尊重)

我为什么要检测它?假设我需要许多需要少于 256 个值的变量,因此它们可以是 8、16、32 位,但是使用正确的大小(与内存和寄存器相同)将加快速度并节省内存,如果这不能在代码中决定,我必须为每个架构重新编写函数

编辑 看完答案后发现这篇文章不错

http://embeddedgurus.com/stack-overflow/category/efficient-cc/page/4/

我将引用结论(加粗)

因此 底线是这个。如果你想 开始写作高效、便携 嵌入代码,第一步你 应该采取的是开始使用C99 数据类型“最少”和“快速”。如果你的 编译器不兼容 C99 抱怨直到它是 - 或改变 供应商。如果您进行此更改,我 觉得你会惊喜 在代码大小的改进和 您将达到的速度。

【问题讨论】:

  • 使用 char、int、short 等类型是不好的做法,应该禁止用于嵌入式系统。我见过一个允许您更改每种类型的长度的编译器(CodeWarrior)。只需使用 types.h 头文件即可。

标签: c optimization embedded cpu-registers


【解决方案1】:

我必须为每个架构重新编写函数

不,你没有。使用 C99 的 stdint.h,它有像 uint_fast8_t 这样的类型,这将是一种能够快速保存 256 个值的类型。

然后,无论平台如何,类型都会相应更改,而您无需更改代码中的任何内容。如果您的平台没有定义这些,您可以添加自己的。

比重写每个函数要好得多。

【讨论】:

  • +1 这是一个解决方案,我认为更标准(无论如何我仍然无法检测到硬件的宽度)
  • @Hernan:不足为奇。 C 不关心实现,而宽度是需要使用某些特定于操作系统的 API 公开的东西。
  • Codewarrior 编译器似乎不符合 C99,我会听从 Embeddedgurus.com 的建议,投诉或更改供应商 =P
  • 一旦我开始使用stdint.h,我就再也没有回头。这比任何事情都更便于携带。
  • @Gerhard,不过我真的希望它是 C++ 中的标准。 =]
【解决方案2】:

为了更直接地回答您的更深层次的问题,如果您需要跨平台可移植的非常特定的存储大小,您应该使用像 types.h stdint.h 这样定义指定存储类型的东西位数。

例如,uint32_t 始终是无符号的 32 位,int8_t 始终是有符号的 8 位。

【讨论】:

  • +1 这是一个解决方案(无论如何我仍然无法检测到硬件的宽度)
  • @sbi:它们在手册页中被称为精确宽度整数。但是我提到了不正确的头文件。它不是types.h,而是stdint.h。我正在纠正答案。
【解决方案3】:
#include <limits.h>

const int bitwidth = sizeof(int) * CHAR_BIT;

【讨论】:

    【解决方案4】:

    您正在编译的ISA 在运行您的代码时已经为编译器所知,因此最好的办法是在编译时检测它。根据您的环境,您可以使用从 autoconf/automake 风格的东西到较低级别的 #ifdef 的所有内容来调整您的代码以适应它将运行的特定架构。

    【讨论】:

    • 复杂的方式。按照 Paul 和 Andrey 的建议使用 sizeof(int) * CHAR_BIT
    【解决方案5】:

    我不完全理解您所说的“没有将“int”用作“寄存器宽度”的标准。在原始 C 语言规范 (C89/90) 中,int 类型隐含在某些上下文中当没有提供显式类型时。您的register c 等效于register int c,这在C89/90 中是完全标准的。另请注意,C 语言规范要求类型int 至少支持-32767...+32767 范围,这意味着在任何平台上int 将至少有 16 个值形成位。

    至于位宽...sizeof(int) * CHAR_BIT 将为您提供int 类型的对象表示中的位数。

    但理论上,int 类型的值表示不能保证使用其对象表示的所有位。如果您需要确定用于值表示的位数,您可以简单地分析INT_MININT_MAX 的值。

    附:查看您问题的标题,我怀疑您真正需要的只是 CHAR_BIT 值。

    【讨论】:

    • 问题是在 16 位或 8 位架构中,CHAR_BIT、INT_MIN 和 INT_MAX 具有相同的值,因此我不能将其用于检测,至少在大多数常见的微控制器编译器中是这样。我认为 int 的标准,从 16 位及以上开始
    • @Hernán:你是说在这些架构上CHAR_BIT==INT_MIN==INT_MAX?这是荒谬的!确定任何类型T 的位数的符合标准的方法是sizeof(T)*CHAR_BIT
    • @sbi,它们在这个意义上具有相同的值,CHAR_BIT(8 位)= CHAR_BIT(16 位),INT_MIN(8 位)= INT_MIN(16 位)等。
    • @Hernán: 那么char 在这两种架构上的大小相同,int 也是如此。那你有什么问题?
    • @sbi,我必须检测架构才能知道是使用 char 还是 int,我想要一个 -via preprocessor selected type- 当有 8 位寄存器时定义我一个 8 位 var,和 16 位,当有 16 位寄存器时,这种类型对于 16、32、64 来说完全是“int”.. 但是在 8 位中,我遇到的问题是 int 是 16 位宽..
    【解决方案6】:

    unsigned charunsigned short 是否适合您的需求?为什么不使用它?如果没有,您应该使用编译时标志来引入适当的代码。

    【讨论】:

    • 在与默认机器字大小之间进行转换时存在开销,因此使用尽可能小的变量并不是最好的方法
    【解决方案7】:

    我认为在这种情况下,您不需要知道您的架构有多少位。如果要优化代码,只需使用尽可能小的变量。

    【讨论】:

    • 鉴于问题的最后一段,我认为这是要走的路。如果所有值都小于 256,请使用 uint8_t。当您的 CPU 将其复制到寄存器中时,它将根据需要对其进行符号扩展以填充寄存器的其余部分。您应该看到使用小于寄存器大小的数字不会降低性能。最好的办法是使用stdint.h 中可以代表所有值的最小数据类型。
    • 也许,但我认为 unsigned char 是最便携的答案,只是因为 stdint.h 来自 C99,而不是以前的
    猜你喜欢
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多