2010-10-07 3 views
1
#include<stdio.h> 
int main(void) 
{ 
    signed int a=-1; 
    unsigned int b=1; 
    int c= a+b; 
    printf("%d\n",c); 

    return 0; 
    } 

В соответствии с правилом преобразования неявного типа, если один операнд unsigned int, другой будет преобразован в unsigned int и результат будет в двоичной операции unsigned int. так здесь b является unsigned int, a должен быть типа отлиты в unsigned int .Как беззнаковое целочисленное значение всегда анолита, так что значение a будет 1.so c=1+1=2 .Но на выходе 0 .Как?Неявные преобразования типов

+0

Я считаю, что это поведение, определяемое реализацией (или неопределенным?), Которое вы испытываете. – strager

+0

@strager: да, поведение присвоения 'c' определено реализацией. 6.3.1.3/3: «новый тип подписан, и значение не может быть представлено в нем, либо результат определяется реализацией, либо повышается сигнал, определяемый реализацией». –

+4

Вы оба ошибаетесь. Соответствующее преобразование происходит от подписанного до unsigned, а не без знака для подписания, и поведение корректно определено. '-1' уменьшается по модулю' UINT_MAX + 1', что приводит к 'UINT_MAX', а добавление 1 к этому снова приводит к уменьшению по модулю' UINT_MAX + 1' и, следовательно, 0. Преобразование 0 обратно в подписанный тип затем хорошо определено , –

ответ

16

-1, когда cast to unsigned станет наибольшим возможным значением для этого типа - например, с 32-битным без знака, это будет 4 294 967 295. Когда вы добавляете 1 к этому, значение «обертывается» до 0.

+0

@ Jerry Coffin, так что если я взял подписанный int a = -2 и unsigned b = 1, то тогда выход будет 4 294 967 295? Но выход -1. – Parikshita

+0

% d выводит подписанный int. Попробуйте% u. –

+0

@Parixit: да, потому что 'c' подписан. – JoshD

-1

Современные машины в основном используют two's complement Представление для отрицательных чисел. Когда добавляются два числа, если какой-либо из них отрицательный, он будет сначала преобразован в представление представления двух. то эти два числа будут добавлены. Поэтому компьютеры обычно выполняют 1 - 1 как 1 + two's complement of (-1). Это приводит к 0.

Для 1 - 2 это 1 + two's complement(-2). Проверьте эту программу, то же число, другое представление:

int main() 
{ 
    signed int a = 1; 
    unsigned int b = -2; 

    int c = a+b; 

    printf("%d\n%u\n", c, c); 

    return 0; 
} 

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

+0

Поведение добавления не имеет ничего общего с представлением о дополнении двух. Это было бы одинаково на одной машине дополнения, вплоть до того момента, когда результат присваивается 'c' (который определяется реализацией, как говорит strager). –

+0

-1 двухкомпонентное дополнение не имеет отношения к вопросу OP, который имеет такое же поведение при ** любой реализации ** C. Ваш новый пример основан на реализации, специфичном для реализации двух дополнений. –

+0

Мое намерение состояло в том, чтобы сделать OP осведомленным о наиболее распространенной реализации. извините, я должен был отметить это в оригинальном ответе. – Donotalo

2

«a должно быть напечатано по типу без знака int. Поскольку unsigned int всегда + ve, значение a будет равно 1."

Откорректируйте до «будет», но не после этого ;-)

В результате преобразования целого числа без знака, чтобы указан в стандарте, 6.3.1.3/2:

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

Другими словами, отрицательное значение преобразуется в беззнаковое, принимая его значение по модулю некоторой мощности 2, а не переворачивая знак.

+0

, так что -1% UINT_MAX снова будет -1 .. – Parikshita

+0

Нет, потому что -1 не представляется в виде беззнакового int, поэтому он не может быть результатом преобразования ничего в unsigned int. В стандарте есть сноска, в которой говорится, что «сложение» или «вычитание» относится к действительным математическим числам, а не к операторам '+' или '-' любого конкретного типа C. То же самое касается моего использования «modulo» - я имею в виду математическую операцию, приводящую к значению в диапазоне '[0, UINT_MAX]'. Я не имею в виду подписанный '%' оператор. –

+0

Это, как математик по образованию, я иногда иногда думаю о непознанных значениях как о абстрактных членах кольца по модулю 'UINT_MAX'. В этом случае да, результат сокращения -1 по модулю 'UINT_MAX + 1' по-прежнему равен -1, но в модели, где -1 равно' UINT_MAX'. Вероятно, не разумно сделать эту вашу ментальную модель целых без знака, хотя, поскольку модель не описывает некоторые операции С, такие как деление. –

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