Сравнение unsigned int и int без использования оператора приведения

Все, что я искал, существует тема по моему вопросу, но я не мог найти.

unsigned int x = 5; 
int y = -3;
if(y<x)
   func1();
else
   func2();

func2 называется . Но я хочу, чтобы func1 позвонили.

Я знаю, что должен использовать оператор приведения при сравнении этих значений.
Но нельзя использовать оператор приведения или изменять тип переменной.

Как я могу решить эту проблему?


person Erdem ŞİMŞEK    schedule 04.06.2015    source источник
comment
stackoverflow.com/a/8233184/4185106   -  person moffeltje    schedule 04.06.2015
comment
Если предупреждения о преобразованиях включены, компилятор всегда должен генерировать их при таких сравнениях без явного приведения. Даже если вы отметите (y ‹ 0) перед сравнением. Так что без гипса не обойдешься (да и не стоит!). Собственно так и следует использовать приведение: с полным пониманием проблем. Стиль кодирования для C, который полностью запрещает приведение типов, но не требует предупреждений о подписи (и большинства/всех других предупреждений), заходит слишком далеко.   -  person too honest for this site    schedule 04.06.2015


Ответы (4)


Сначала проверьте, является ли y отрицательным значением, а затем, зная это, вы знаете, что x всегда будет больше, поскольку оно беззнаковое.

Если y не является отрицательным, то сравните его значение непосредственно с x. Я не думаю, что это вызовет проблему, поскольку отрицательного знака нет.

См. приведенный ниже пример:

if(y<0)
{
    //x>y
    func1();
}
else if (y<x)
{
    //lets say y=3, and x=5
    func1();
}
else
{
    func2();
}
person Javia1492    schedule 04.06.2015

Вы можете записать условие в операторе if следующим образом

if( y < 0 || y<x)
   func1();
else
   func2();
person Vlad from Moscow    schedule 04.06.2015
comment
Это по-прежнему будет генерировать предупреждение для сравнения. К сожалению, стили кодирования полностью запрещают приведение типов, но не применяют предупреждения. Приведения иногда делают иногда имеют смысл. Этот пример на самом деле является прекрасным доказательством. - person too honest for this site; 04.06.2015

Используйте более широкую целочисленную математику для сравнения. Приведение не используется, тип переменных не изменяется.
Оптимизированный компилятор не будет выполнять умножение, а только целочисленное расширение.
Вместо этого можно использовать * 1LL или + 0LL

int main(void) {
  long long ll = 1;
  unsigned int x = 5;
  int y = -3;
  // if (y < x)
  if (ll * y < ll * x)
    puts("func1();");
  else
    puts("func2();");
  return 0;
}

Output: func1();

long long обычно шире, чем int: См. Как определить целочисленные типы, которые в два раза шире, чем `int` и `unsigned`?

person chux - Reinstate Monica    schedule 04.06.2015

Попробуйте дополнить y (~y), получится 2

unsigned int x = 5; 
int y = -3;
if(~y<x)
   func1();
else
   func2();
person venge    schedule 04.06.2015
comment
Спасибо. Используя это обозначение ~y, возьмем ли мы первое дополнение переменной y? - person Erdem ŞİMŞEK; 04.06.2015
comment
@ user3151801 Это неправильное условие. Рассмотрим случай, когда y равно -3, а x равно 2. - person Vlad from Moscow; 04.06.2015
comment
ну тогда вы можете добавить INT_MAX к ним обоим и сравнить. #include ‹limits.h› - person venge; 04.06.2015
comment
Это поведение, определяемое реализацией, так как оно основано на дополнительном представлении 2. Это даже не работает для y == INT_MIN И что, если x >= -(llong long)(INT_MIN) (предположительно long long имеет больше битов, чем int)? - person too honest for this site; 04.06.2015