'maximum (and minimum) off_t

I could not find something like OFF_MAX that would tell me the maximum allowed value for off_t so I wonder if I could perhaps use that:

#define OFF_MAX ~((off_t)1 << (sizeof(off_t) * 8 - 1))
#define OFF_MIN  ((off_t)1 << (sizeof(off_t) * 8 - 1))

I know bit operations on signed values is generally undefined, but is it ok for x86 and ARM, Windows (mingw), Linux and Mac OS X?



Solution 1:[1]

In C++ (not C), you could just say

static constexpr off_t OFF_MIN = std::numeric_limits<off_t>::min();
static constexpr off_t OFF_MAX = std::numeric_limits<off_t>::max();

In C, you don't have that generic API, so your macros are pretty close to the best you can do. One thing to watch out for is bit-twiddling involving the sign bit: (1 << 31) - 1 triggers undefined behavior, so the result isn't necessarily 0x7fffffff even on real-world systems. (Godbolt.) So you should at least change your bit-twiddling to something like this:

#define OFF_MAX ((((off_t)1 << (sizeof(off_t)*8 - 2)) - 1) * 2 + 1)
#define OFF_MIN (-OFF_MAX - 1)

Next, for portability to DSPs with 24- or 32-bit char, or simply to get rid of that magic number 8, we could do this:

#define OFF_MAX ((((off_t)1 << (sizeof(off_t)*CHAR_BIT - 2)) - 1) * 2 + 1)
#define OFF_MIN (-OFF_MAX - 1)

Portability to sign-magnitude or ones'-complement platforms (which essentially do not exist in practice) is left as an exercise for the reader. :) Also these macros are not portable to an actively malicious DeathStation 9000 implementation — like, if sizeof(off_t) == 128 but 124 of those bytes are just padding.

But instead of doing all this bit-twiddling, in practice you should just do this:

#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)

Systems where off_t is neither 32-bit nor 64-bit are, IMHO, neither common nor valuable.


Finally... I have basically no experience here, but it seems to me that usually when you want to know the effective "max" of off_t, it's because you're about to do something like ftruncate(fd, x) and you want to know whether x is going to throw you an EFBIG error instead of succeeding. In that case, you really need something operation-specific, something that is to OFF_MAX as RSIZE_MAX is to SIZE_MAX (see Why is rsize_t defined? ), or analogous to MAX_PATH or PIPE_BUF from <linux/limits.h> or RAND_MAX from <stdlib.h>.

On some systems, the point-at-which-EFBIG-starts-happening might be accessible (at runtime) via something like this:

// #include <sys/resource.h>
rlimit lim;
getrlimit(RLIMIT_FSIZE, &lim);
printf("%zu %zu\n", (size_t)lim.rlim_cur), (size_t)lim.rlim_max));

On my MacBook, that just prints SIZE_MAX, so it's not very useful.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Quuxplusone