Неоднозначность в сравнении чисел (в C)? - PullRequest
6 голосов
/ 13 мая 2011

Я не слишком знаком с программированием на C (я только сделал несколько небольших проектов на языке), однако, мой профессор сказал кое-что о его поведении сегодня, что немного смутило меня.

Он сказал, что этот код иногда вообще ничего не печатает (я скопировал именно то, что было на плате, я считаю, что это псевдокод для C, поскольку "print" не в C):

    int a = ___________;
    int b = ___________;

    if (a < b)
   print (“<“);
    if (a > b)
   print (“>”);
    if (a==b)
   print(“=”);

По сути, есть кое-что, что вы можете сохранить в тех переменных int, где ни одно из этих условий не будет выполнено ( _ __ _ не соответствует действительности Код, очевидно, просто представляет, что что-то есть) Это не обязательно должен быть какой-то int, который заполняет эти пробелы ... это может быть что угодно в мире (и может быть что-то, что происходило до этого кода).

Что может заполнить эти пробелы и не дать никакого результата, и почему?

p.s - это было связано с переполнением, неопределенным поведением, ошибкой выхода за границы или чем-то подобным

p.p.s - У меня серьезные проблемы с верой, что этот профессор ошибся. Он знает больше о программировании, чем кто-либо, с кем я когда-либо сталкивался. Я убежден, что в некоторых случаях это так.

Ответы [ 8 ]

4 голосов
/ 13 мая 2011

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

int b = *(int *)0;
2 голосов
/ 13 мая 2011

Полагаю, важна часть _ . Если подчеркнутая часть содержит код, который приводит к поведению UNDEFINED, и следующий код со сравнениями получает , оптимизированный"умным" компилятором по неопределенному поведению, окончательное поведение этого фрагмента кода не определено. И не печатать ничего - разумное неопределенное поведение.

p.s. Согласно Википедии, деление на ноль приводит к неопределенному поведению, хотя большинство компиляторов определяют это как ошибку. И переполнение целых чисел со знаком IIRC также вызывает неопределенное поведение, хотя, опять же, это обычно вызывает исключение во время выполнения или даже ошибку компиляции. Так что если a и b объявлены как

int a = 1 / 0;
int b = INT_MAX + 1;

ситуация, которую описывает ваш проф. Но помните, что поведение не определено, поэтому, какой бы компилятор ни выбирал программу для себя, он может считаться соответствующим стандарту.

1 голос
/ 13 мая 2011

Если у вас есть архитектура с целыми числами в одном дополнении, существует два нуля: один со всеми битами, установленными в 0, и один со всеми битами, установленными в 1, иначе положительный и отрицательный ноль. Оба ноля должны сравниваться одинаково, но глючный компилятор может этого не видеть; -)

0 голосов
/ 13 мая 2011

Может быть, определение print:

void
print(const char*) {    
}
0 голосов
/ 13 мая 2011

Учитывая, что "может быть что-то, что произошло до этого кода" ...

#include <stdio.h>
#include <math.h>

int main(void)
{

#define int float

    int a = nanf(NULL);
    int b = nanf(NULL);

    if (a < b)
       printf("<\n");
    if (a > b)
       printf(">\n");
    if (a == b)
       printf("==\n");

    return 0;
}
0 голосов
/ 13 мая 2011
a = 0, b = 5 / a : divide by zero
0 голосов
/ 13 мая 2011

пс - возможно, это как-то связано с переполнением?

Я думаю, это то, что имел в виду ваш профессор:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char** argv)
{
    uint8_t a = 100;
    uint8_t b = 200;

    a = a + b; /* a = 300 in your head. This overflows, so 300-256=44 */

    if ( a > b )
    {
        printf("%u > %u", a, b);
    }
    else if ( a < b )
    {
        printf("%u < %u", a, b);
    }
    else
    {
        printf("%u == %u", a, b);
    }

    return 0;
}

В частности, яиспользование 8-разрядного целого числа без знака фиксированной ширины, которое может содержать максимум 8 бит (неожиданно), что представляет 256 как максимально возможное целое число.Вы можете переполнить это поле, добавив к нему сумму, которая не может быть представлена ​​в этом размере, и в этом случае останется эффект обтекания.

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

Примечание. Я использовал введенные в C99 целые числа фиксированного размера для ясности и малых чиселтак что мы можем сделать это в нашей голове.

0 голосов
/ 13 мая 2011

Для int это не так, потому что у них нет «специальных» значений.

...