Приведите ssize_t или size_t

В исходных файлах, которые я использую в своем проекте, есть сравнение между переменными ssize_t и size_t:

ssize_t sst;
size_t st;

if(sst == st){...}

Я хотел бы избавиться от предупреждения:

warning: comparison between signed and unsigned integer expressions

Но я не уверен, какую переменную я должен привести к другой?

if((size_t)sst == st){...}

or

if(sst == (ssize_t)st){...}

Что безопаснее, лучше, чище? Спасибо


person rluks    schedule 18.04.2013    source источник
comment
Какой язык вы используете?   -  person    schedule 18.04.2013
comment
Попробуйте добавить (signed int) перед целым числом без знака. Теперь оно должно быть целым числом со знаком и больше не будет вызывать ошибку.   -  person    schedule 18.04.2013
comment
@Allendar: приведение size_t к int - это рецепт катастрофы. На 64-битных платформах int обычно имеет ширину всего 32 бита.   -  person Fred Foo    schedule 18.04.2013
comment
+1 @ларсманс. И даже если бы они были одинакового размера, если значение без знака не может быть представлено в переменной со знаком, это вызывает поведение, определяемое реализацией, что делает код (предположительно) менее переносимым.   -  person Carl Norum    schedule 18.04.2013
comment
@Allendar: Я очень, очень надеюсь, что никогда не увижу, чтобы кто-то так делал.   -  person Stephen Canon    schedule 18.04.2013


Ответы (2)


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

  • Если вы знаете, что sst неотрицательно, то можете смело приводить sst к size_t, так как это не изменит значение (кстати, это то, что происходит, если у вас вообще нет приведения).

  • Если sst может быть отрицательным, но вы знаете, что st никогда не будет больше SSIZE_MAX, то вы можете безопасно преобразовать st в ssize_t, так как это не изменит значение.

  • Если sst может быть отрицательным, а st может быть больше, чем SSIZE_MAX, то ни одно из приведений не является правильным; любой из них может изменить значение, что приведет к неправильному сравнению. Вместо этого вы должны сделать следующее if (sst >= 0 && (size_t)sst == st).

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

person Stephen Canon    schedule 18.04.2013
comment
+1 за более простое выражение - нет причин включать (st <= SSIZE_MAX) в свой ответ. - person Carl Norum; 18.04.2013

Любой из них будет работать нормально, если оба значения соответствуют положительному представимому диапазону ssize_t.

Если одно из значений не соответствует, у вас могут возникнуть проблемы — проверьте эти случаи перед проверкой на равенство:

if ((sst >= 0) && (st <= SSIZE_MAX) && (sst == (ssize_t)st))
{
  ...
}

(Я уверен, что люди, работающие с С++, порекомендуют вам полностью избегать приведения типов в стиле C — я не сомневаюсь, что кто-то прокомментирует или ответит и сообщит вам, как правильно сделать это на С++.)

person Carl Norum    schedule 18.04.2013
comment
Как только вы исключите sst < 0, вы можете просто преобразовать в size_t и сравнить. - person Stephen Canon; 18.04.2013
comment
static_cast<ssize_t>(st) — несколько более безопасное приведение C++. - person Yakk - Adam Nevraumont; 18.04.2013