Максимальное (и минимальное) off_t
Я не мог найти что-то вроде OFF_MAX
что бы сказать мне максимально допустимое значение для off_t
так что мне интересно, если бы я мог использовать это:
#define OFF_MAX ~((off_t)1 << (sizeof(off_t) * 8 - 1))
#define OFF_MIN ((off_t)1 << (sizeof(off_t) * 8 - 1))
Я знаю, что битовые операции со значениями со знаком обычно не определены, но нормально ли это для x86 и ARM, Windows (mingw), Linux и Mac OS X?
1 ответ
В 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.) Так что вы должны по крайней мере изменить свою бит-вертушку на что-то вроде этого:
#define OFF_MAX ((((off_t)1 << (sizeof(off_t)*8 - 2)) - 1) * 2 + 1)
#define OFF_MIN (-OFF_MAX - 1)
Далее, для переносимости на DSP с 24- или 32-битным
char
, или просто избавиться от этого магического числа
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)
Системы, где нет ни 32-битных, ни 64-битных, ИМХО, не распространены и не ценны.
Наконец... У меня здесь практически нет опыта, но мне кажется, что обычно, когда вы хотите узнать эффективный "максимум"
off_t
, потому что вы собираетесь сделать что-то вродеftruncate(fd, x)
и вы хотите знать,
x
собирается выдать вам ошибку вместо успеха. В этом случае вам действительно нужно что -то конкретное для операции , что-то, что
OFF_MAX
в качестве
RSIZE_MAX
(см. Почему определено rsize_t? ) или аналогично
MAX_PATH
или же
PIPE_BUF
из<linux/limits.h>
или жеRAND_MAX
из
<stdlib.h>
.
В некоторых системах точка, в которой
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
, так что это не очень полезно.