为什么没有 INT_BIT?

Why isn't there an INT_BIT?

为什么 limits.h 中有 _BIT 宏用于 CHAR_BITLONG_BITWORD_BIT?为什么它不定义 INT_BIT?

为什么这些宏是为其他类型定义的,而不是为 int 定义的? sizeof 是否已弃用(不再使用)?

我看到这些是由 POSIX for limits.h

定义的

看起来 WORD_BIT 是您想要成为的 INT_BIT,从您 link 到的文档:

{WORD_BIT} Number of bits in an object of type int.

请注意 CX 表示这是对标准 C 的扩展。

C99 rationale document 告诉我们,除了 CHAR_BIT 之外,委员会没有其他理由:

The macro CHAR_BIT makes available the number of bits in a char object. The C89 Committee saw little utility in adding such macros for other data types.

可能是因为 CHAR_BIT*sizeof(type) 满足了您的需求。

您可以在构建时通过计算相应无符号最大值中的位数来生成它们。

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
int popcnt(unsigned long long X) { int pc=0;for(;(X&1);pc++,X>>=1){;} return pc; }
int main()
{
    if(0>printf("#define CHAR_BIT %d\n", popcnt(UCHAR_MAX))) return EXIT_FAILURE;
    if(0>printf("#define UCHAR_BIT %d\n", popcnt(UCHAR_MAX))) return EXIT_FAILURE;
    if(0>printf("#define SCHAR_BIT %d\n", popcnt(UCHAR_MAX))) return EXIT_FAILURE;
    if(0>printf("#define SHRT_BIT %d\n", popcnt(USHRT_MAX))) return EXIT_FAILURE;
    if(0>printf("#define USHRT_BIT %d\n", popcnt(USHRT_MAX))) return EXIT_FAILURE;
    if(0>printf("#define INT_BIT %d\n", popcnt(UINT_MAX))) return EXIT_FAILURE;
    if(0>printf("#define UINT_BIT %d\n", popcnt(UINT_MAX))) return EXIT_FAILURE;
    if(0>printf("#define LONG_BIT %d\n", popcnt(ULONG_MAX))) return EXIT_FAILURE;
    if(0>printf("#define ULONG_BIT %d\n", popcnt(ULONG_MAX))) return EXIT_FAILURE;
    if(0>printf("#define LLONG_BIT %d\n", popcnt(ULLONG_MAX))) return EXIT_FAILURE;
    if(0>printf("#define ULLONG_BIT %d\n", popcnt(ULLONG_MAX))) return EXIT_FAILURE;
    if(0>fclose(stdout)) return EXIT_FAILURE;
    return EXIT_SUCCESS;
}

在我的平台上,以上内容让我:

#define CHAR_BIT 8
#define UCHAR_BIT 8
#define SCHAR_BIT 8
#define SHRT_BIT 16
#define USHRT_BIT 16
#define INT_BIT 32
#define UINT_BIT 32
#define LONG_BIT 64
#define ULONG_BIT 64
#define LLONG_BIT 64
#define ULLONG_BIT 64

(请注意,这些在技术上不能保证为 sizeof(the_type)*CHAR_BIT,因为 C 标准允许在本机类型中填充位。)

如果 运行 在您想要支持的任何平台上构建之前的这段代码对您来说很烦人,我理解您。

使用这个小 shell 脚本,您可以生成(每个平台一次)一个完美的整数常量表达式保留无 UB 调用(希望如此)popcnt cpp 宏用于最多 N 位整数:

#!/bin/sh -eu
gen()
{
    Max=
    local i=0;
    prev='(X)'
    #continuous popcount at compile time
    printf '#define contpopcnt(X) %s\n' "(($prev&1)\"
    i=1; while [ $i -le $Max ]; do
        #look 1 bit ahead the left shift never reaches or exceeds 
        #the width of whatever X's type might be (would be UB)
        prev="(($prev&2)?((X)>>$i):0)"
        printf '+(%s&1)\\n' "$prev"
    i=$((i+1));done
    printf ')\n'
}

gen 256
cat<<EOF
//#define CHAR_BIT contpopcnt(UCHAR_MAX)
#define UCHAR_BIT contpopcnt(UCHAR_MAX)
#define SCHAR_BIT contpopcnt(UCHAR_MAX)
#define SHRT_BIT contpopcnt(USHRT_MAX)
#define USHRT_BIT contpopcnt(USHRT_MAX)
#define INT_BIT contpopcnt(UINT_MAX)
#define UINT_BIT contpopcnt(UINT_MAX)
#define LONG_BIT contpopcnt(ULONG_MAX)
#define ULONG_BIT contpopcnt(ULONG_MAX)
#define LLONG_BIT contpopcnt(ULLONG_MAX)
#define ULLONG_BIT contpopcnt(ULLONG_MAX)

//a little sanity check
#include <limits.h>
#include <stdint.h>
#if CHAR_BIT!=contpopcnt(UCHAR_MAX)
    #error "oops"
#endif
EOF

并且宏的 256 位变体只有 (!) 605KB。所以你真的不需要那些 *_BIT 宏。

编辑:

这里有一个更紧凑的方式:。