2017-01-11 6 views
3

По моему мнению, для простых операций с 8-битными переменными переменные преобразуются в 32 бит int с до завершения операции, а затем преобразуются обратно в 8-битные переменные.Почему uint8_t + uint8_t приводит к int?

В качестве примера, это с программой ++:

#include <iostream> 
#include <cstdint> 

int main(void) 
{ 
    uint8_t a = 1; 
    uint8_t b = 2; 

    std::cout << "sizeof(a) = " << sizeof(a) << std::endl; 
    std::cout << "sizeof(b) = " << sizeof(b) << std::endl; 
    std::cout << "sizeof(a+b) = " << sizeof(a+b) << std::endl; 

    return 0; 
} 

Производит следующий вывод:

sizeof(a) = 1 
sizeof(b) = 1 
sizeof(a+b) = 4 

Таким образом, мы могли понять, что происходит, является:

uint8_t c = (uint8_t)((int)(a) + (int)(b)); 

По-видимому, это похоже, находится в спецификации C, как сказано в форуме this.

Кроме того, в Visual Studio 2013, написание

auto c = a + b; 

И наведя указатель мыши на c указывает, что тип int.

Вопросов:

  • Почему требуется преобразование, почему в спецификации? (Если возможно, с ответом, я бы хотел, чтобы внешние источники информации читали больше по этому вопросу (например, MSDN, cppreference).)
  • Как это влияет на производительность?

ответ

2

Вопросов:

  • Почему необходимо преобразование, почему в спецификации? (Если возможно, с ответом, я бы хотел, чтобы внешние источники информации читали больше по этому вопросу (например, MSDN, cppreference).)
  • Как это влияет на производительность?

Ну

  • Требования к арифметических операторов С ++, чтобы принять целые операнды могут быть найдены here:

  • Правила Integral Promotions можно найти here.

Что касается того, почему его в спецификации. Гипотетически ... Хотя у процессоров могут быть инструкции, которые могут работать с 8-битными целыми числами, внутри ЦП целые числа записи/чтения, которые меньше ширины регистра, могут включать маскировку, о которой вы не знаете.

Скажите, что вы имеете ширину регистра 32 бит. Добавление двух 8-битных целых чисел обычно требует некоторой маскировки для приема 8-битных частей и заполнения оставшихся 24-битов нулями ... ALU будет выполнять свою работу с данными в регистрах и сохранять результаты в полной записи регистра (32 бита). Затем еще одна маскировка для получения результатов в виде 8-битного целого числа, если вы отбрасываете обратно.

Так что продвигать его не стоит ничего, потому что CPU все равно это сделает.

См. On 32-bit CPUs, is an 'integer' type more efficient than a 'short' type?.

Даже ваш regular 32bit operations on 64bits

6

Это связано с правилами integral promotion. Конкретно

Prvalues ​​малых интегральных типов (такие, как char) может быть преобразован в более крупного prvalues ​​интегральных типов (такие, как int). В частности, арифметические операторы не принимают типы, меньшие, чем int, как аргументы, и интегральные рекламные акты автоматически применяются после преобразования lvalue-to-rvalue, если это применимо. Это преобразование всегда сохраняет значение.

+1

* "Почему преобразование необходимо, почему это в спецификации?" * – WhiZTiM

+1

Представьте, что вы делаете 'uint8_t а = 200, B = 100, с = 2; uint8_t d = (a + b)/c; 'без поощрения промежуточный результат будет переполняться - с продвижением все заканчивается на 150, который подходит в пункте назначения. –

+3

@JesperJuhl * ".. без продвижения промежуточный результат будет переполняться" * - 'int a = INT_MAX, b = 343232; int c = a + b' все равно будет переполняться ... Итак? – WhiZTiM

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