2012-06-21 2 views
4

Игры с некоторыми источниками нашли такой код:Проверьте, без знака меньше нуля

void foo(unsigned int i) 
{ 
if(i<0) 
    printf("Less then zero\n"); 
else 
    printf("greater or equ\n"); 
} 

int main() 
{ 
    int bar = -2; 
    foo(bar); 
    return 0; 
} 

Я думаю, нет смысла, но может быть есть некоторые случаи (безопасность?), Что делает эту проверку SensAble?

+0

Спасибо за ваши ответы! Вы укрепили мою уверенность. Но кто-то написал это. Может быть, есть некоторые платформы или компиляторы, которые думают иначе? – dtoch

+0

Может быть небольшое изменение точных значений для конверсий с подписью/без знака в зависимости от размера int в вашей системе (см. Ответы, связанные с jonnyGold и wap26). Но все компиляторы выдают исполняемые файлы, которые в этом случае демонстрируют одно и то же поведение потока управления. Другими словами - нет :) Тот, кто написал это, вероятно, не заметил, что эта ситуация с потоком контроля (ошибка) или же они экспериментируют. – erapert

+0

Кажется, что ты прав. Я проверил несколько проверок. НКУ просто удаляет любые проверки и написать строку: 'Foo: PushL% EBP MOVL% особ,% EBP subl $ 24,% особ MOVL $ .LC0, (% особ) вызов ставит оставить ret' Clang генерирует чек, но: 1. недействительного Foo (беззнаковый INT I) рядного 'Foo + 19: Jae 0x804841f ' 2. аннулируется Foo (подпись INT I): рядного 'Foo + 19: JGE 0x804841f ' – dtoch

ответ

13

Беззнаковое значение int не может быть меньше 0 по определению. Поэтому, чтобы более точно ответить на ваш вопрос, вы правы, думая, что это не имеет никакого смысла. Это не значимый элемент безопасности, если вы не встретите что-то вроде цикла, который случайно уменьшает подписанный int прошлый 0, а затем передает его как unsigned int для использования в качестве индекса в массив и, следовательно, индексирует память за пределами массива.

+1

[Этот ответ] (http://stackoverflow.com/questions/50605/signed-to-unsigned-conversion-in-c-is-it-always-safe) проливает свет на то, что происходит, когда вы бросаете из отрицательного в t к неподписанному int. – bluevector

2

i всегда будет >=0, потому что он объявлен как unsigned и поэтому интерпретируется как целое число без знака. Итак, ваш первый тест всегда будет ложным.

Ваш звонок foo(bar) фактически преобразует int в unsigned int. Возможно, это смущает вас. И «преобразование» фактически не изменяет значение байтов/бит вашего целого, это просто вопрос формальной типизации и интерпретации.

См. Это answer для примеров преобразований с подписью/без знака.

Вот простой пример (точный вывод зависит от количества байтов unsigned int в вашей системе, для меня это 4 байта).

Код:

printf("%u\n", (unsigned int) -2); 

Выход:

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