Умножение char и int вместе в C - PullRequest
6 голосов
/ 16 апреля 2010

Сегодня я нашел следующее:

#include <stdio.h>

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

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

return 0;

}

Так что в основном я получаю переполнение, потому что ограничение размера определяется операндами справа от знака = ??

Почему не преобразуется в int перед умножением работы?

В этом случае я использую char и int, но если я использую "long" и "long long int" (c99), я получаю похожее поведение. Как правило, не рекомендуется делать арифметику с операндами разных размеров?

Ответы [ 4 ]

11 голосов
/ 16 апреля 2010

char может быть подписанным или неподписанным, в зависимости от вашего компилятора.

В вашем случае он, кажется, подписан, а 255 находится вне диапазона, который он может представлять (вероятно, он может представлять только числа от -128 до 127).

Таким образом, проблема возникает, когда вы присваиваете 255 переменной char - это приводит к определенному реализацией значению, которое в вашем случае будет равно -1.

Когда вы умножаете -1 на 2, вы получаете -2. Там нет никакой тайны. Приведение к (int) ничего не делает - типы, более узкие, чем int, всегда переводятся в int или unsigned int до того, как с ними будут выполнены любые вычисления.

5 голосов
/ 16 апреля 2010

Похоже, что char подписан на вашей платформе. Таким образом, char x = 255 фактически совпадает с char x = -1. Приведение к int не имеет значения.

Попробуйте изменить это на:

unsigned char x = 255;
4 голосов
/ 16 апреля 2010

Нет, вы не получаете переполнение во второй строке (умножение). Проблема в том, что ваш компилятор использует signed char по умолчанию и переполнение 255 и будет означать -1. По сути, вы инициализируете переменную x значением -1. Приведение -1 к int приведет к -1 (signed операнды получат расширение знака в upcast, тогда как unsigned операнды получат расширение ноль).

Вы можете заставить char быть unsigned, добавив префикс unsigned:

unsigned char x = 255;
3 голосов
/ 16 апреля 2010

Другие ответы хорошо объясняют, как ваш пример «работает», поэтому я не буду объяснять это снова.

Однако, позвольте мне заметить, что если вы хотите использовать "8-разрядное целое число без знака", просто используйте uint8_t *1004* уже (и его 16, 32, 64-битные компаньоны) и держитесь подальше от всех char с, short с и int с в этом мире.

...