Это "ошибка" компилятора. Чтобы уточнить это:
Как правило, сравнение между знаком и без знака основано на количествах, определенных реализацией (размеры / диапазоны типов). Например, USHRT_MAX == -1
верно для обычных 16-битных систем и false для обычных 32-битных систем. Ответ "забвения" более детально про это говорит.
Все ваши примеры кода четко определены и ведут себя одинаково во всех (соответствующих) системах.
Цель этого предупреждения двоякая:
- чтобы предупредить вас о коде, который может вести себя по-другому в других системах.
- чтобы предупредить вас о коде, который может вести себя не так, как задумал кодер.
Впрочем, в общем. статическому анализу компилятора не так-то просто разобраться в первом случае, не говоря уже о втором, довольно субъективном.
IMO предупреждение, для вашего кода, является ошибкой, потому что код четко определен и не о чем предупреждать.
Лично я не включаю это предупреждение: я знаком с правилами сравнения со знаком без знака и предпочитаю избегать искажения моего кода для подавления предупреждения.
Переходя к противоположной крайности, некоторые люди предпочитают избегать всех сравнений со знаком без знака в своем коде, даже если он четко определен; и они посчитали бы ошибкой то, что компилятор не предупредил о ваших первых трех примерах кода.
GCC имеет тенденцию слишком часто ошибаться в сторону предупреждения, но они находятся в ситуации, когда не могут угодить всем.