Переполнение в c - PullRequest
       12

Переполнение в c

2 голосов
/ 29 апреля 2009

У меня есть сомнения

Когда два 16-битных значения добавляются с максимальными значениями, будет ли переполнение в 16-битных машинах?

Я уточню

unsigned short a;
unsigned short b;
unsigned long  c;

c=(unsigned long)(a+b);

Если говорить о 16-битных процессорах, то аккумулятор будет 16-битным. Будет ли переполнение в приведенном выше утверждении? Пожалуйста, уточните.

Ответы [ 2 ]

13 голосов
/ 29 апреля 2009

С этими определениями и предполагая unsigned short == 16 бит и int == 16 бит и unsigned long == 32 бит (обратите внимание, что размер int важен):

unsigned short a, b;
unsigned long  c;

Эти два утверждения будут делать разные вещи:

c = (unsigned long)(a + b);
c = (unsigned long)a + b;

Первый - тот, который вы показали - сначала добавит числа в виде беззнаковых шорт, исключая любое переполнение, и , а затем расширится до беззнакового длинного. Это может быть то, почему вы спрашиваете. Второй приведёт a к длинному без знака, затем добавит два числа, увеличивая b до длинного без знака, прежде чем делать сложение.

Вы также можете сделать это:

c = (unsigned long)a + (unsigned long)b;

но это не обязательно, так как наличие одного неподписанного длинного в расчете приведет к автоматическому переходу другого размера с короткого на длинный.

Таким образом:

a = 0x8001;
b = 0x8001;
c = (unsigned long)(a + b);   /* c is assigned 0x00000002 */
c = (unsigned long)a + b;     /* c is assigned 0x00010002 */

Все это зависит от вашего конкретного компилятора и от размера его переменных. Это конкретно зависит от размера int вашего компилятора, поскольку все значения автоматически повышаются до int или unsigned int во время вычислений. Вы упомянули аппаратное обеспечение с 16-разрядными аккумуляторами, и компиляторы C обычно (но не всегда) используют собственный размер регистра в качестве размера int, поэтому я предположил int в качестве 16-разрядных.

9 голосов
/ 29 апреля 2009

Да, будет переполнение. Подвыражение a + b имеет тип short, и только после того, как оно будет оценено, результат будет приведен к long. Сделайте это:

c = (unsigned long)a + b;

Это приведет к тому, что a будет приведен к длинному до того, как произойдет добавление, и это, в свою очередь, также приведет к тому, что b будет приведен к длинному Следовательно, происходит добавление двух длинных, и переполнение не произойдет.

...