Максимальное (и минимальное) 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, так что это не очень полезно.

Другие вопросы по тегам