在 C++(不是 C)中,你可以说
static constexpr off_t OFF_MIN = std::numeric_limits<off_t>::min();
static constexpr off_t OFF_MAX = std::numeric_limits<off_t>::max();
在 C 语言中,您没有通用 API,因此您的宏非常接近您可以做到的最佳水平。需要注意的一件事是涉及符号位的位旋转:(1 << 31) - 1 会触发未定义的行为,因此即使在实际系统上,结果也不一定是0x7fffffff。 (Godbolt.) 所以你至少应该把你的 bit-twiddling 改成这样:
#define OFF_MAX ((((off_t)1 << (sizeof(off_t)*8 - 2)) - 1) * 2 + 1)
#define OFF_MIN (-OFF_MAX - 1)
接下来,为了移植到具有 24 位或 32 位 char 的 DSP,或者只是为了摆脱那个神奇的数字 8,我们可以这样做:
#define OFF_MAX ((((off_t)1 << (sizeof(off_t)*CHAR_BIT - 2)) - 1) * 2 + 1)
#define OFF_MIN (-OFF_MAX - 1)
符号幅值或反码平台(在实践中基本上不存在)的可移植性留给读者作为练习。 :) 此外,这些宏不能移植到恶意的 DeathStation 9000 实现中——例如,如果 sizeof(off_t) == 128 但其中 124 个字节只是填充。
但不要做所有这些琐碎的事情,实际上你应该这样做:
#define OFF_MAX (sizeof(off_t) == sizeof(long long) ? LLONG_MAX : sizeof(off_t) == sizeof(int) ? INT_MAX : -999999)
#define OFF_MIN (sizeof(off_t) == sizeof(long long) ? LLONG_MIN : sizeof(off_t) == sizeof(int) ? INT_MIN : -999999)
off_t 既不是 32 位也不是 64 位的系统,恕我直言,既不常见也不有价值。
最后...我在这里基本上没有经验,但是在我看来通常当您想知道off_t的有效“最大值”时,这是因为您即将做类似ftruncate(fd, x) 的事情,你想知道x 是否会抛出EFBIG 错误而不是成功。在这种情况下,你真的需要一些操作特定的东西,就像RSIZE_MAX 和SIZE_MAX 一样(参见Why is rsize_t defined?),或者类似于MAX_PATH 或@ 987654344@ 来自<linux/limits.h> 或RAND_MAX 来自<stdlib.h>。
在某些系统上,可以通过以下方式访问 point-at-which-EFBIG-starts-happening(在运行时):
// #include <sys/resource.h>
rlimit lim;
getrlimit(RLIMIT_FSIZE, &lim);
printf("%zu %zu\n", (size_t)lim.rlim_cur), (size_t)lim.rlim_max));
在我的 MacBook 上,它只打印 SIZE_MAX,所以它不是很有用。