gcc 扩展或宏,用于在编译时检查用于某些基本类型的位
Gcc extension or macro to check the bits used for some fundamental types at compile time
在编译时,有些人使用 static_assert
我想检查一些简单类型(如 unsigned int
或 char
)的大小,重要的是根据我的使用情况,它将在编译时发生。
我在gcc
手册中没有找到任何关于此的内容,也不了解clang
提供的类似功能,有人知道如何检查类型使用的位数吗?
没有大小,请,我的重点是位和编译时间.
没有大小,请,我的重点是位和编译时间.
保持开放的心态;-P
#include <cstdint>
static_assert(sizeof(X) * CHAR_BIT == 32, "type X must be 32 bits in size");
1. 如何在不使用CHAR_BIT
宏的情况下查找类型中的位数
如果类型是数值类型(如 int
和 char
),则可以使用 std::numeric_limits<T>::digits
获取有效位数,假设T
是二进制类型(即std::numeric_limits<T>::radix == 2
)。这些是constexpr
的,因此它们可以用于 static_assert
.
实现可能无法使用某些数字类型(char
除外)中的所有存储位,在这种情况下,有效位数可能与以位为单位的物理大小无关。此外,符号位不计算在内,因此您需要添加std::numeric_limits<T>::is_signed
以获取非填充位的数量。
由于char
类型不允许有填充和char
,signed char
和unsigned 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>
不必是实际文件。
笔记
- 以上都不适用于 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__
- 具有多个模板的模板函数,用于特定数据类型(如字符串)?
- 需要帮助在 c++ 中将字符串转换为字符 ----错误 "const char *" 类型的值不能用于初始化 "char" 类型的实体
- 为什么 std::lerp 不适用于任何已实现所需操作的类型?
- 给定一个类型,如何派生一个泛型更广泛的类型(例如,用于溢出安全求和)?
- 用于检测函数类型是否为否的特征
- Clang 工具,用于提取给定 lambda 类型的 lambda 主体
- C++中是否有用于长数据类型的 lower_bound() 函数?
- 用于随机数据访问的最有效文件类型
- 用于C++代码的 API 监视器类型定义 (XML)
- "const wchar_t *" 类型的值不能用于初始化类型 "const PWSTR" 的实体
- 矢量类型规范中的星号用于什么?
- 与不同变量类型相比,用于变量的 Clang AST 匹配器
- C++ 自动用于类型和非类型模板
- 用于类型转换的元函数
- 用于类型转换的接口,而不是强制转换
- 用于类型转换空指针的类型/类的向量
- SFINAE用于类型实例化
- 如何理解这段用于类型检查的C++代码
- 提取可变参数模板参数包,并将其用于类型特征元函数中的另一个可变参数模板
- 用于类型转换或转发的功能(取决于输入类型)