gpt4 book ai didi

c - 如何正确找到 off_t 大小

转载 作者:行者123 更新时间:2023-12-02 10:43:58 26 4
gpt4 key购买 nike

我的模块中有以下代码,我用 ICC 编译器编译它。

/**
* Static (compile-time) assertion.
* Basically, use COND to dimension an array. If COND is false/zero the
* array size will be -1 and we'll get a compilation error.
*/

#define STATIC_ASSERT(COND) \
do { \
(void) sizeof(char [1 - 2*!(COND)]); \
} while (0)
#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + \
(((off_t) 1 << 31) << 31))
STATIC_ASSERT(LARGE_OFF_T % 2147483629 == 721 &&
LARGE_OFF_T % 2147483647 == 1);

上述断言失败,数组大小必须大于 0。

谁能帮我理解这个断言何时失败以及如何解决它?
我曾尝试使用 _DFILE_OFFSET_BITS=64 进行编译,但徒劳无功。

最佳答案

该代码尝试确定 off_t至少 64 位宽,包括一个符号位。

STATIC_ASSERT , 如果 COND是真的,1 - 2*!(COND)计算为 1-2*!1 = 1-2*0 = 1 ,并且数组大小为1,这很好。如果 COND为假,计算结果为 1-2*!0 = 1-2*1 = -1 ,这会导致编译器发出诊断。所以STATIC_ASSERT如果 COND 则生成编译器消息是假的。
LARGE_OFF_T尝试在 off_t 中执行一些算术运算类型。如果 off_t至少 64 位宽,(off_t) 1 << 31) << 31计算结果为 262。然后整个表达式计算结果为 262 - 1 + 262 = 263-1。这个数字有 721 模 2147483629 和 1 模 2147483647 的余数,因此它通过了测试并且不会导致编译器发出诊断。

如果 off_t例如,32 位宽且无符号,(off_t) 1 << 31) << 31计算结果为 0,整个表达式计算结果为 0 − 1 + 0 = 232−1(因为无符号算术换行),其余数模 2147483629 为 37,因此它未通过测试,编译器生成诊断。

如果 off_t 则测试不可靠已签署。如果 off_t有符号且 32 位宽,(off_t) 1 << 31 的行为不是由 C 标准定义的。如果它是有符号的并且小于 63 位宽,((off_t) 1 << 31) << 31 的行为是未定义的,并且,如果它是有符号的且小于 64 位宽,则最后的加法是未定义的。

如果您的测试失败,您需要通过调整构建条件来纠正它,以便 off_t是至少 64 位宽的整数类型。问题中没有足够的信息来说明如何执行此操作。

代码中有迹象表明它需要 off_t成为有符号类型。如果已知它是无符号的,那么只需测试 18446744073709551615u <= (off_t) -1 就可以确保它至少为 64 位。 .代码尝试构造的值 263−1 是 64 位有符号整数的最大值,而不是无符号整数。这是不幸的,因为如上所述,如果 off_t有符号且宽度小于 64 位,操作具有未定义的行为。更好的方法可能是测试 9223372036854775807 == (off_t) 9223372036854775807 ,因为转换为有符号整数类型期间的溢出至少是实现定义的,而不是 C 标准未定义的。也可以选择64 <= sizeof(off_t) * CHAR_BIT . ( CHAR_BIT<limits.h> 中定义。)

关于c - 如何正确找到 off_t 大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60261831/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com