NO_*_*AME 27 c++ language-lawyer c++17
我需要知道是否intmax_t
始终“相同类型”,除非uintmax_t
使用二进制补码而不是无符号值。
或者用正式的术语来说,下面的代码是否总是在符合标准的编译器中编译?
#include <cstdint>
// The important assertion:
static_assert(sizeof(std::uintmax_t) == sizeof(std::intmax_t));
// Less important assertions:
static_assert(UINTMAX_MAX == static_cast<std::uintmax_t>(INTMAX_MAX) * 2 + 1);
static_assert(-static_cast<std::intmax_t>(UINTMAX_MAX / 2) - 1 == INTMAX_MIN);
Run Code Online (Sandbox Code Playgroud)
我对 C++17 特别感兴趣。
我知道 C++20 是强制执行二进制补码的标准的第一个版本,但变量的大小对我来说比表示形式更重要。
duc*_*uck 29
是的,uintmax_t
保证是 的未签名副本intmax_t
。
根据 C 标准 (N1570 7.20.1):
当定义 typedef 名称仅因首字母不存在或存在而不同时
u
,它们应表示相应的有符号和无符号类型,如 6.2.5 中所述;提供这些对应类型之一的实现也应提供另一个。
(对于 C 标准库头的描述,C++ 简称为 C。)
6.2.5 p6:
对于每个有符号整数类型,都有一个对应的(但不同的)无符号整数类型(用关键字指定
unsigned
),它使用相同的存储量(包括符号信息)并具有相同的对齐要求。
C++ 在这方面与 C 类似 ( [basic.fundamental]/3 ):
对于每个标准有符号整数类型,都存在一个对应的(但不同的)标准无符号整数类型[...],它与对应的有符号整数类型占用相同的存储量并具有相同的对齐要求;也就是说,每个有符号整数类型与其对应的无符号整数类型具有相同的对象表示形式。同样,对于每个扩展有符号整数类型,都存在具有相同存储量和对齐要求的相应扩展无符号整数类型。
这意味着intmax_t
和uintmax_t
始终具有相同的大小。
但是,不能保证其他两个断言成立(C++20/C23 之前)。
Chr*_*sMM 11
从评论/标题来看,您似乎是在问它们是否需要相同的尺寸;在这种情况下,简短的答案是肯定的......长答案......有点:)
\n引用自[basic.fundamental]/3
(C++17 草案 N4713)
\n\n对于每个标准有符号整数类型,都存在相应的(但不同)标准无符号整数类型: \xe2\x80\x9cunsigned char\xe2\x80\x9d、\xe2\x80\x9cunsigned Short int\xe2\x80\x9d 、 \xe2\x80\x9cunsigned int\xe2\x80\x9d、\xe2\x80\x9cunsigned long int\xe2\x80\x9d 和 \xe2\x80\x9cunsigned long long int\xe2\x80\x9d,每个与其对应的有符号整数类型占用相同的存储量并具有相同的对齐要求。
\n
(强调我的)
\n这保证了未签名版本占用与其签名版本相同的大小。
\n话虽这么说,标准[cstdint.syn]
仅规定:
\n\n使用 intmax_t =有符号整数类型;
\n使用 uintmax_t =无符号整数类型;
\n
美国[basic.fundamental]/2
\n\n标准和扩展有符号整数类型统称为有符号整数类型。
\n
和[basic.fundamental]/3
各州
\n\n标准和扩展无符号整数类型\n统称为无符号整数类型
\n
因此,从技术上讲,编译器不必将它们实现为同一类型,因为这是一个实现细节;但实际上,它们是相同的。
\n正如 duck 所指出的,C 标准确实表明带前缀u
和不带u
前缀的类型之间必须存在对应的版本。C 标准是通过引用的[cstdint.syn]/2