gcc 扩展或宏,用于在编译时检查用于某些基本类型的位

Gcc extension or macro to check the bits used for some fundamental types at compile time

本文关键字:用于 类型 检查 扩展 编译 gcc      更新时间:2023-10-16

在编译时,有些人使用 static_assert 我想检查一些简单类型(如 unsigned intchar)的大小,重要的是根据我的使用情况,它将在编译时发生。

我在gcc手册中没有找到任何关于此的内容,也不了解clang提供的类似功能,有人知道如何检查类型使用的位数吗?

没有大小,请,我的重点是和编译时间.

没有大小,请,我的重点是位和编译时间.

保持开放的心态;-P

#include <cstdint>
static_assert(sizeof(X) * CHAR_BIT == 32, "type X must be 32 bits in size");

1. 如何在不使用CHAR_BIT宏的情况下查找类型中的位数

如果类型是数值类型(如 intchar ),则可以使用 std::numeric_limits<T>::digits 获取有效位数,假设T是二进制类型(即std::numeric_limits<T>::radix == 2)。这些是constexpr的,因此它们可以用于 static_assert .

实现可能无法使用某些数字类型(char除外)中的所有存储位,在这种情况下,有效位数可能与以位为单位的物理大小无关。此外,符号位不计算在内,因此您需要添加std::numeric_limits<T>::is_signed以获取非填充位的数量。

由于char类型不允许有填充和charsigned charunsigned char要求大小完全相同,std::numeric_limits<unsigned char>::digits必须是char中的位数,也称为所需的宏CHAR_BIT。因此,您可以互换使用这两个表达式,因此任何类型的T的位大小(物理的,无意义的)都将sizeof(T)*std::numeric_limits<unsigned char>::digits

我不认为编译器本身需要知道char的位大小是多少(尽管大多数编译器可能会知道)。它确实需要知道每个基元类型的sizeof(T)是什么。没有标准规定的方法来确定std::numeric_limits<unsigned char>::digits的值,而不包含一些头文件。

2.为什么你不应该担心它。

在独立环境中,<numeric_limits>不是必需的,但<climits>仍然是必需的,因此即使在独立环境中,您也可以依靠CHAR_BIT,而您只能在托管环境中依靠std::numeric_limits<unsigned char>::digits

换句话说,编译器有义务有某种方式来提供#include <climits>的结果,因为即使在独立环境(即没有标准库甚至操作系统的环境中)中,标准也需要该标头。这就是您正在寻找的"内置";即使您没有在标准库实现中提供<climits>,即使您手边没有标准库,编译器仍必须安排在发生#include <climits>后正确定义宏CHAR_BIT。它如何做到这一点取决于编译器; <climits>不必是实际文件。

笔记

  1. 以上都不适用于 C,但static_assert也不起作用,所以我假设将这个问题标记为 C 是一个疏忽。正如@mafso在评论中指出的那样,C11 确实有一个static_assert声明,但它仅适用于 C11 样式的常量表达式,而不适用于 C++ 样式的常量表达式。C++常量表达式可以使用诸如 constexpr 函数之类的东西,这些函数可能是内置的。另一方面,C 常量表达式只能涉及整数文字。它们仍然有用(对于非纯粹主义者),因为宏扩展首先发生,并且宏可以扩展到整数文本(甚至是涉及多个整数文本的表达式)。

根据本文档,gnu 编译器将为您定义这些宏:

__CHAR_BIT__      // bits
__SIZEOF_INT__    // bytes
__SIZEOF_LONG__
__SIZEOF_LONG_LONG__
etc...

您可以从字节宏定义自己的位宏,只需乘以 8。

编辑:由于您显然需要知道"单词大小"并认为指针与"单词"的大小相同,因此请使用以下内容:

__SIZEOF_POINTER__