【问题标题】:Which fixed-width integer types are available有哪些固定宽度的整数类型可用
【发布时间】:2016-02-03 18:09:57
【问题描述】:

所以我正在尝试创建一个使用固定宽度整数的算法的实现。话虽如此,我想使用可用的最大尺寸,同时需要知道其中的位数,因为算法依赖于位移。

我想要一种方法,最好是通过预处理器来确定最大整数类型的宽度(目前我正在使用来自stdint.h 的uintmax_t),但是如果我知道的话,我可以详尽地实现这一点编译器定义/支持的固定宽度类型。

我在我的 PC 上发现了一个旧程序,其中我有 #ifdef __INT64_TYPE__ 的预处理器指令,这是可以通过的,但我不知道这些将在哪里定义,或者在什么标准下。

总而言之,如果有人知道一种方法来计算uintmax_t 中的位数,那将是完美的,但如果不知道我从哪里得到__INT64_TYPE__?

【问题讨论】:

  • 实现不需要提供任何固定整数类型。说明你的目标平台。
  • @moooeeeep 这就是我一直在看的东西,但他们没有告诉我我从哪里得到__INT64_TYPE__,或者任何关于uintmax_t 宽度的信息。 @Olaf 我认为实施是一个糟糕的选择。我希望我的答案是可移植的,但尽可能准确。
  • 一般来说,算法是针对特定精度编写的。因此,您使用定义的类型。如果您真的需要优化速度,那么无论如何您都必须至少采用平台的部分内容。请说明您的实际问题。您可能正在处理某种症状。
  • 你真的需要在预处理指令阶段将宽度作为常量表达式吗?如果没有,您可以使用#define UINTMAX_BITS ((sizeof(uintmax_t) * CHAR_BIT) 来确定位数。

标签: c c-preprocessor primitive-types fixed-width


【解决方案1】:

如果有人知道计算uintmax_t 中位数的方法,那将是完美的,但如果不知道,我从哪里得到 INT64_TYPE?

计算无符号类型的位数很容易。设置为 -1 并计算移位次数,直到 0。

int bc_uintmax_t(void) {
  int bc = 0;
  uintmax_t x = -1;
  while (x) {
    x %= 2;
    bc++;
  }
  return bc;
}

便携在编译时检测uintmax_t 中的位数更难。一个主要的障碍是预处理器算法可能只能工作到intmax_t。因此,除非做出一些假设,否则便携式解决方案可能无法找到。

当然sizeof (uintmax_t) * CHAR_BIT 是该类型可能具有的最大 位宽度。然而可能会出现填充位。

在<stdint.h> 中查找(u)intmax_t 和精确宽度整数类型,如uint64_t。


[编辑]

要在编译时确定常量的值位宽度,代码可以使用以下代码。注意:对于UINTMAX_MAX,我不确定这段代码的可移植性。

#include <stdio.h>
#include <limits.h>

#define ISGE2_1(x)  ((x) >= 2)
#define ISGE2_2(x)  ((x) >= 4)
#define ISGE2_4(x)  ((x) >= 16)
#define ISGE2_8(x)  ((x) >= 256)
#define ISGE2_16(x) ((x) >= 65536)
#define ISGE2_32(x) ((x)/65536 >= 65536)
#define ISGE2_64(x) ((x)/4294967296 >= 4294967296)
#define ISGE2_128(x) ((x)/18446744073709551616 >= 18446744073709551616)

#define BW_1ORLESS(x)   ((x) ?  1 : 0)
#define BW_2ORLESS(x)   (ISGE2_1(x)  ?  1 + BW_1ORLESS(x/2)                     : BW_1ORLESS(x))
#define BW_4ORLESS(x)   (ISGE2_2(x)  ?  2 + BW_2ORLESS(x/4)                     : BW_2ORLESS(x))
#define BW_8ORLESS(x)   (ISGE2_4(x)  ?  4 + BW_4ORLESS(x/16)                    : BW_4ORLESS(x))
#define BW_16ORLESS(x)  (ISGE2_8(x)  ?  8 + BW_8ORLESS(x/256)                   : BW_8ORLESS(x))
#define BW_32ORLESS(x)  (ISGE2_16(x) ? 16 + BW_16ORLESS(x/65536)                : BW_16ORLESS(x))
#define BW_64ORLESS(x)  (ISGE2_32(x) ? 32 + BW_32ORLESS(x/4294967296)           : BW_32ORLESS(x))
#define BW_128ORLESS(x) (ISGE2_64(x) ? 64 + BW_64ORLESS(x/18446744073709551616) : BW_64ORLESS(x))


#if INTMAX_MAX/4294967296 > 4294967296
  #define BW_65PLUS(x) (ISGE2_128(x) ? BW_129PLUS(x) : BW_128ORLESS(x))
  #define BIT_WIDTH_POSITIVE_VALUE(x) (ISGE2_64(x) ? BW_65PLUS(x) : BW_64ORLESS(x))

#else
  #define BW_33PLUS(x) (ISGE2_64(x)   ? BW_65PLUS(x)  : BW_64ORLESS(x))
  #define BIT_WIDTH_POSITIVE_VALUE(x) (ISGE2_32(x) ? BW_64ORLESS(x) : BW_32ORLESS(x))
#endif

// Do not call BIT_WIDTH_POSITIVE_VALUE with negative values.

应用

#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>

int main() {
  printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(true));
  printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(CHAR_BIT));
  printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(SCHAR_MAX));
  printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(SHRT_MAX));
  printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(INT_MAX));
  printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(LONG_MAX));
  printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(LLONG_MAX));
  printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(INTMAX_MAX));
  printf("%d\n", BIT_WIDTH_POSITIVE_VALUE(UINTMAX_MAX));
  return 0;
}

输出

1
4
7
15
31
31
63
63
64

【讨论】:

    【解决方案2】:

    我用过类似的东西

    #if (UINTMAX_MAX > 0xFFFFFFFFFFFFFFF5ULL)
    

    等等

    【讨论】:

    • 为什么最后是5?
    • 我迷信了!毕竟低位并不重要。
    猜你喜欢
    • 1970-01-01
    • 2020-02-05
    • 2023-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多