2016-01-02 3 views
2
size_t a; 
off_t b; 
... 
if(b<a) ... 

Как и ожидалось, компилятор делает предупреждение «подписанный против беззнакового сравнения» здесь, так как off_t подписан, а size_t не имеет знака. Есть ли способ сделать такой компаньон, правильно работать на любой платформе, не используя intmax_t/uintmax_t и условные директивы препроцессора?
Подписанный под заказ без знака

Он должен работать независимо от того, что sizeof (size_t) и sizeof (off_t) равно. Они могут иметь любые значения, например:

sizeof(size_t)=4, sizeof(off_t)=8 (regular modern 32bit unix) 
sizeof(size_t)=4, sizeof(off_t)=4 (older system) 
sizeof(size_t)=8, sizeof(off_t)=4 (some 64bit system with 32bit filesystem support) 

Если я просто типаж один к другому, потери данных и ошибочный результат может произойти.

EDIT Чтобы быть ясным: отрицательные значения b не являются проблемой, так как отрицательный b легко обнаруживается (если (b < 0)) и всегда будет меньше ЛЮБОГО значения без знака a. Проблема заключается в сравнении положительных значений двух таких типов, и я не знаю, какой тип имеет большую ширину.

EDIT2 Это не дублируется «сравнение off_t и ssize_t с другими типами», потому что этот вопрос касается сравнения подписанных типов с различной битовой шириной, и это о подписанных типах без знака; и первый ответ в этом вопросе также не отвечает на этот вопрос, потому что ответ о двух типах одинакового размера, и вот два типа неизвестного размера; также этот вопрос не только о сравнительном, также об уходе ПРЕДУПРЕЖДЕНИЙ

+0

Как будет происходить потеря данных? Разница между ними - это только бит знака. – TheRealChx101

ответ

2
if(b < 0 || (b <= SIZE_MAX && (size_t)b < a)) 

должен работать во всех случаях.

Если b отрицательный, то, очевидно, это меньше, чем a, потому что a не может быть отрицательным (потому что size_t беззнаковым).

Если b больше SIZE_MAX, то, очевидно, это больше, чем a потому a не может быть больше, чем SIZE_MAX.

В противном случае они оба находятся в допустимом диапазоне для size_t, поэтому их достаточно сравнить с size_t.

+0

upv, я собирался опубликовать точно такое же выражение – ouah

+1

, как было сказано в (почему?) Удаленный комментарий, он все равно генерирует предупреждение под знаком/без знака для b <= SIZE_MAX; теперь это не ошибка, но я хочу скомпилировать ее с флагом -Werror, чтобы я искал способ удалить это предупреждение вообще – firk

+0

@immibis кажется, что условие без предупреждения (b <0 || (! (b & ((off_t) SIZE_MAX)) && (size_t) b firk

0

No.

Проблема заключается в том, что «любых ценности» включает в себя отрицательные, в этом случае необходимо применить специальный код для его обработки, поскольку базовая машина этого не делает.

Если вы знаете, что ваши значения гарантированы неотрицательными, просто отбросьте их на неподписанный тип, соответствующий самому большому операнду.

Смежные вопросы