2013-07-31 5 views
3

В приведенном ниже коде я умножил 0xffffffff на 2 для unsigned int (32 бит) и сохранил его в unsigned long long (64 бит). Почему бы мне не получить фактический результат, который равен 8589934588. Вместо этого я получаю 4294967294. Спасибо заранее. ВЫХОД: Sizeof я = 4 Sizeof J = 8 2xi = 4294967292unsigned int (32 бит) до беззнакового длинного длинного (64 бит)

/* Code starts here */ 
#include <stdio.h> 
#include <stdlib.h> 

int main (void) 
{ 
    unsigned int i=4294967294; 
    unsigned long long j=i*2; 
    printf("Sizeof i=%d\n", sizeof(i)); 
    printf("Sizeof J=%d\n", sizeof(j)); 
    printf("2xi=%llu\n", j); 

    return 0; 
} 

ответ

5

Это потому, что i*2 является целым числом многократно. Несмотря на то что вы сохраняете его в long long, вы по-прежнему выполняете математику целых чисел, что вызывает переполнение.

Следующий код работает, так как мы продвигаем его до long long умножить

#include <stdio.h> 
#include <stdlib.h> 
int main (void) 
{ 
    unsigned int i=4294967294; 
    unsigned long long j=((unsigned long long)i)*2; 
    printf("Sizeof i=%d\n", sizeof(i)); 
    printf("Sizeof J=%d\n", sizeof(j)); 
    printf("2xi=%llu\n", j); 

    return 0; 
} 

Результат:

bash-4.1$ gcc long.c 
bash-4.1$ ./a.out 
Sizeof i=4 
Sizeof J=8 
2xi=8589934588 
+2

Помните, что 'signed overflow' - это неопределенное поведение, но неподписанное переполнение просто обертывает. –

3

i*2 ничего не знает о том, что это время назначен на unsigned long long - так i является a unsigned int и 2 - int умножение выполняется с использованием типа unsigned int, что дает t в результате вы получили.

Вы можете решить эту проблему, сделав 2unsigned long long буквальным, что способствует i к unsigned long long для умножения или литья i к unsigned long long перед умножением, который имеет тот же эффект:

unsigned long long j=i*2ULL; 
/* or */ 
unsigned long long j=((unsigned long long)i)*2; 

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

2

Поскольку i является unsigned int и 2 является int и будет повышен до unsigned int операция будет просто обернуть вокруг. Одним из решений было бы бросить i к unsigned long long:

unsigned long long j = ((unsigned long long)i)*2 ; 

Соответствующий раздел из draft C11 standard в 6.2.5/9: никогда не может переполнения, , потому что результат, который не может быть представлен

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