От новичка до гуру: Курсы программирования на CyberDuff

Как протестировать приведенный ниже код? Что произойдет, если я передам целое число со знаком для переменной, объявленной как «целое число без знака»?

Я хочу знать диапазон чисел, которые можно использовать для «a» и «b» без ошибки (т.е. вывод также должен давать правильное значение.)

#include <stdio.h>
#include <stdlib.h>

int sum(int * , int *);

int main()
{
unsigned int a= 10;
int b = -30,c;

c=sum(&a,&b);
printf("sum of %d and %d is %d",a,b,c);

return 0;
}

int sum(int *p , int *q)
{
return *p+*q;
};

Я дал число со знаком переменной «a», которая объявлена ​​как целое число без знака, и «-30» для переменной «b». Я получил правильный вывод для значений больше -2147483618 (-2147483617, -2147483616 и т. д.). Но я получил положительные значения для a=-2147483619 и далее. Почему это так? Пожалуйста, помогите мне.

31.03.2015

  • Смешивание целых чисел без знака и со знаком в выражении приводит к безумию. 31.03.2015
  • Несколько небольших замечаний: почему функция ; после суммы? а зачем передавать указатели на сумму, когда можно было бы передать их нормально? 31.03.2015
  • Вы имеете в виду больше -2147483648 вместо -2147483618? Вы просто выходите за пределы диапазона переменной int 31.03.2015

Ответы:


1

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

31.03.2015

2

Как упоминалось в комментариях, проблема в том, что вы выходите за диапазон диапазонов integer и unsigned integer. Это причина, почему вы получаете неожиданный результат. По этой ссылке:

int 2 байта: от -32 768 до 32 767
int 4 байта: от -2 147 483 648 до 2 147 483 647
unsigned int 2 байта: от 0 до 65 535
unsigned int 4 байта: от 0 до 4 294 967 295

В вашем случае, когда b (или результат сложения a и b) имеет значение ниже -2 147 483 648 или выше 2 147 483 647, оно переполняется и будет иметь неопределенное поведение (например: то, что вы получаете, положительное значение для сложения двух отрицательных значений).

Подробнее о целочисленном переполнении и о том, как C его обрабатывает, можно прочитать на этой странице Википедии.

31.03.2015
  • Примечание. В C целочисленное переполнение, как и в a+b, является поведением undefined. 31.03.2015

  • 3

    Для int единственным переносимым решением является использование INT_MIN и INT_MAX, поскольку переполнение int является неопределенным поведением. Итак, чтобы найти диапазон int, выведите эти два.

    Поскольку переполнение с unsigned хорошо определено, максимальное unsigned всегда равно:

    unsigned maxu = -1;  // -1 converts to the maximum unsigned
    unsigned minu = 0;
    

    Итак, учитывая unsigned_a + int_b --> int_c, что-то вроде следующего обнаружит переполнение. Во 2-й половине, вероятно, есть проблемы, подлежащие уточнению.

    bool SumWithOverflowDetect(unsigned a, int b, int *c) {
      if (b >= 0) {
        if (INT_MAX - b < a) return true;
        *c = a + b;
      } else {
        unsigned sum = a + b; // converts b to unsigned before the addition
        if (sum > a) return true;
        if (sum > INT_MAX) return true;
        *c = sum;
      }
      return false;
    }
    

    Более простой способ обнаружения переполнения использует int2x

    bool SumWithOverflowDetect2(unsigned a, int b, int *c) {
      // int2x is some type wider than int/unsigned
      int2x sum = (int2x) a + (int2x) b;
      if (sum < INT_MIN || sum > INT_MAX) return true;
      *c = (int) sum;
      return false;
    }
    
    31.03.2015
    Новые материалы

    Основы Spring: Bean-компоненты, контейнер и внедрение зависимостей
    Как лего может помочь нашему пониманию Когда мы начинаем использовать Spring, нам бросают много терминов, и может быть трудно понять, что они все означают. Итак, мы разберем основы и будем..

    Отслеживание состояния с течением времени с дифференцированием снимков
    Время от времени что-то происходит и революционизирует часть моего рабочего процесса разработки. Что-то более забавное вместо типичного утомительного и утомительного процесса разработки. В..

    Я предполагаю, что вы имеете в виду методы обработки категориальных данных.
    Я предполагаю, что вы имеете в виду методы обработки категориальных данных. Пожалуйста, проверьте мой пост Инструментарий специалиста по данным для кодирования категориальных переменных в..

    Игра в прятки с данными
    Игра в прятки с данными Я хотел бы, чтобы вы сделали мне одолжение и ответили на следующие вопросы. Гуглить можно в любое время, здесь никто не забивается. Сколько регионов в Гане? А как..

    «Раскрытие математических рассуждений с помощью Microsoft MathPrompter и моделей больших языков»
    TL;DR: MathPrompter от Microsoft показывает, как использовать математические рассуждения с большими языковыми моделями; 4-этапный процесс для улучшения доверия и рассуждений в математических..

    Раскройте свой потенциал в области разработки мобильных приложений: Абсолютная бесплатная серия
    Глава 6: Работа в сети и выборка данных Глава 1: Введение в React Native Глава 2: Основы React Native Глава 3: Создание пользовательского интерфейса с помощью React Native Глава 4:..

    Все о кейсах: Camel, Snake, Kebab & Pascal
    В программировании вы сталкивались с ними при именовании переменной, класса или функции. Поддержание согласованности типов и стилей случаев делает ваш код более читабельным и облегчает совместную..