'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 |