Да, здесь "внаглую" используется переполнение
Вот нашел.
http://www.viva64.com/en/d/0225/print/This is how the C++11 standard describes shift operators' work:
2. The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are
zero-filled. If E1 has an unsigned type, the value of the result is E1 * 2^E2,
reduced modulo one more than the maximum value representable in the result type.
Otherwise, if E1 has a signed type and non-negative value, and E1*2^E2 is
representable in the result type, then that is the resulting value; otherwise,
the behavior is undefined.
off_t max = 1;
while((max << 1) > 0){ max = (max << 1) | 1;}
Как я понимаю, в данном случае E1*2^E2 не представимо типом результата, т. к.
становится отрицательным, и, стало быть, undefined behavior. Обложили со всех
сторон.
идёте, смотрите что такое off_t и делаете на основании этого пару своих дефайнов
Я даже на своем компьютере не нашел, что такое
off_t, сложно. Надо
чтоб само собой работало, без помощи человека.
Вы,
venco, предложили использовать беззнаковый
тип того же размера. Но я же заранее не знаю этот тип, это может быть
long intили
long long int. А для
off_t нет сопряженного типа
uoff_t.
А если через
sizeof? Примерно так:
int i, bits = sizeof(off_t) * 8;
off_t max = 1;
for(i=0; i < (bits - 2); i++){ max = (max << 1) | 1;}
Офтоп (а в настоящем офтопе код не отображается)
Я даже вспомнил случай с UB при переполнении, он заключается в том, что в
этом куске кода (ниже), при компиляции с
-O3, если
s переполняется
и становится отрицательным, то проверка
if(s < 0) не работает. Без
оптимизации работает. Наверно, это и есть маленькое UB.
s=0;
while(*p1>='0' && *p1<='9'){
s = (s * 10) + ((*p1++) - '0');
}
if(s < 0){}