C: неявное приведение и целочисленное переполнение при вычислении выражений - PullRequest
2 голосов
/ 08 сентября 2008

Давайте возьмем код

int a, b, c;
...
if ((a + b) > C)

Если мы добавим значения a и b и сумма превысит максимальное значение типа int, будет ли нарушена целостность сравнения? Я думал, что может быть неявная проверка приведения или переполнения, и это будет учтено при оценке этого выражения.

Ответы [ 5 ]

7 голосов
/ 08 сентября 2008

C не будет делать такие вещи. Это тихо переполнится и приведет к возможно неправильному сравнению. Вы можете повысить свою роль, но это не будет сделано автоматически.

2 голосов
/ 09 сентября 2008

Тест подтверждает, что GCC 4.2.3 будет просто сравнивать с переполненным результатом:

#include <stdio.h>

int main()
{
    int a, b, c;

    a = 2000000000;
    b = 2000000000;
    c = 2100000000;

    printf("%d + %d = %d\n", a, b, a+b);
    if ((a + b) > c)
    {
        printf("%d + %d > %d\n", a, b, c);
    }
    else
    {
        printf("%d + %d < %d\n", a, b, c);
    }
    return 0;
}

Отображает следующее:

2000000000 + 2000000000 = -294967296
2000000000 + 2000000000 < 2100000000
0 голосов
/ 14 июня 2009

Если обновление не дает вам никаких битов (нет гарантии, что sizeof (long)> sizeof (int) в C), вы можете использовать условия, подобные приведенным ниже, для сравнения и проверки на переполнение - upcasting почти наверняка быстрее если вы можете использовать его, хотя.

#if !defined(__GNUC__) || __GNUC__<2 || (__GNUC__==2 && __GNUC_MINOR__<96)
#   define unlikely(x) (x)
#else
#   define unlikely(x)     (__extension__ (__builtin_expect(!!(x), 0)))
#endif

/* ----------
 * Signed comparison (signed char, short, int, long, long long)
 * Checks for overflow off the top end of the range, in which case a+b must
 * be >c.  If it overflows off the bottom, a+b < everything in the range. */
if(a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
    ...

/* ----------
 * Unsigned comparison (unsigned char, unsigned short, unsigned, etc.)
 * Checks to see if the sum wrapped around, since the sum of any two natural
 * numbers must be >= both numbers. */
if(a+b>c || unlikely(a+b<a))
    ...

/* ----------
 * To generate code for the above only when necessary: */
if(sizeof(long)>sizeof(int) ? ((long)a+b>c)
       : (a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
    ...

Отличный кандидат для макросов или встроенных функций. Вы можете использовать «маловероятные», если хотите, но они могут помочь уменьшить и ускорить код, сгенерированный GCC.

0 голосов
/ 09 сентября 2008

См. Раздел 2.7, Преобразования типов в книге K & R

0 голосов
/ 08 сентября 2008

Полагаю, это может зависеть от платформы. Посмотрите документацию C о том, как обрабатываются переполнения ...

Ах да, и подъем не произойдет автоматически ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...