我需要知道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);
我对C17特别感兴趣。
我知道C20是第一个强制执行二进制补码的标准版本,但对我来说,变量的大小比表示更重要。
3条答案
按热度按时间afdcj2ne1#
是的,
uintmax_t
保证是intmax_t
的无符号对应项。根据C标准(N1570 7.20.1):
当定义的typedef名称仅在缺少或存在初始
u
方面不同时,它们应表示6.2.5中所述的相应的有符号和无符号类型;提供这些对应类型之一的实现也将提供另一种。(C只是简单地引用C来描述C标准库头文件。)
6.2.5第6页:
对于每一个有符号整数类型,都有一个对应的(但不同的)无符号整数类型(用关键字
unsigned
指定),该类型使用相同的存储量(包括符号信息)并具有相同的对齐要求。C在这方面与C类似([basic.fundamental]/3):
对于每个标准有符号整数类型,存在对应的(但不同的)标准无符号整数类型[...],其占用相同的存储量并且具有与对应的有符号整数类型相同的对齐要求;即,每个有符号整数类型具有与其对应的无符号整数类型相同的对象表示。同样,对于每个扩展有符号整数类型,存在具有相同存储量和对齐要求的对应的扩展无符号整数类型。
这意味着
intmax_t
和uintmax_t
始终具有相同的大小。然而,它不能保证另外两个Assert将成立(在C++20/C23之前)。
epfja78i2#
从评论/标题来看,你似乎在问它们是否需要相同的大小;在这种情况下,简短的答案是肯定的...长答案...有点:)
引用自
[basic.fundamental]/3
(C++17草案N4713)对于每种标准无符号整数类型,都存在对应的(但不同的)标准无符号整数类型:"unsigned char"、"unsigned short int"、"unsigned int"、"unsigned long int"和"unsigned long long int",其中每种类型与其对应的有符号整数类型占用相同的存储量,并且具有相同的对齐要求。
(着重号是我的)
这保证了无符号版本与有符号版本占用相同的大小。
也就是说,标准
[cstdint.syn]
仅声明:使用intmax_t =* 有符号整数类型 ;
使用uintmax_t = 无符号整数类型 *;
[basic.fundamental]/2
状态标准和扩展有符号整数类型统称为 * 有符号整数类型 *。
和
[basic.fundamental]/3
状态标准和扩展无符号整数类型统称为 * 无符号整数类型 *
因此,从技术上讲,编译器不必将它们实现为相同的类型,因为这是一个实现细节;但实际上,他们是一样的
正如duck所指出的,C标准确实指出了具有
u
前缀和没有u
前缀的类型之间必须有对应的版本。rpppsulh3#
我的答案被达克证明是错误的。谢谢,达克!
https://stackoverflow.com/a/75203111/2027196
我原来的回答供以后参考:
uintmax_t
和intmax_t
并不保证 * 由标准 * 具有相同的宽度,但是现代C编译器中不存在它们具有不同宽度的系统,甚至可能不存在它们具有不同宽度的非现代C编译器(* 在没有证据的情况下Assert,与“天空是蓝色的”类型参数相同 *)。你能得到的最好的结果是
uintmax_t
和intmax_t
被保证 * 按照约定 * 是相同的宽度。我说“你能得到的最好的结果”,但是我愿意更经常地依赖这个保证,而不是依赖一个编译器完美地实现它所有的边缘情况SFINAE要求或类似要求。把你的
static_assert
放在你的库的顶部(也许在assumptions.hpp
文件中),然后再也不用担心这个问题了。