2010-04-16 17 views
6

Dziś znalazłem następujące:Mnożąc char i int razem w C

#include <stdio.h> 

int main(){ 
char x = 255; 
int z = ((int)x)*2; 

printf("%d\n", z); //prints -2 

return 0; 

} 

więc w zasadzie Dostaję przepełnienie ponieważ limit rozmiaru zależy od argumentów po prawej stronie znaku = ??

Dlaczego nie przesyłasz go do int przed pomnożeniem pracy?

W tym przypadku używam char i int, ale jeśli używam "long" i "long long int" (c99), otrzymuję podobne zachowanie. Czy generalnie odradza się robienie arytmetyki operandami o różnych rozmiarach?

Odpowiedz

11

char może być albo znakiem lub bez, w zależności od kompilatora.

W twoim przypadku wygląda na to, że jest podpisany, a 255 jest poza zakresem, który może reprezentować (prawdopodobnie może reprezentować tylko liczby od -128 do 127).

Problem pojawia się, gdy przypiszesz 255 do zmiennej char - w wyniku tego powstanie wartość zdefiniowana przez implementację, która w twoim przypadku wygląda na -1.

Po pomnożeniu -1 przez 2 otrzymujesz -2. Nie ma tam tajemnicy. Obsada do (int) nic nie robi - typy węższe niż int są zawsze promowane do int lub unsigned int przed dokonaniem jakichkolwiek obliczeń.

4

Nie, w drugim wierszu nie pojawia się przepełnienie (mnożenie). Problem polega na tym, że Twój kompilator domyślnie używa signed char, a przepełnienie 255 oznacza -1. Zasadniczo inicjujesz zmienną x o wartości -1. Rzucanie -1 do int spowoduje -1 (signed operandów zostanie rozszerzonych o znak w upcasts podczas gdy operandy unsigned zostaną rozszerzone zero).

można wymusić char być unsigned dodając przedrostek unsigned:

unsigned char x = 255; 
5

Wydaje się, że char jest podpisany na swojej platformie. Tak więc char x = 255 jest faktycznie taki sam jak char x = -1. Odlewanie do int nie ma znaczenia.

Spróbuj zmienić które do:

unsigned char x = 255; 
3

Inne odpowiedzi dobrze wyjaśniają, jak twój przykład "działa", więc nie będę tego wyjaśniał ponownie.

jednak, pozwól mi zauważyć, że jeśli to, co chcesz użyć jest „bez znaku 8 bitową liczbę całkowitą”, wystarczy użyć <stdint.h> „s uint8_t już (i jego 16, 32, towarzyszy 64bit) i trzymać z dala od wszystkich char s , short s oraz int s na tym świecie.

+1

#include dla tych typów. – slartibartfast