Приведение типов C ++ при передаче аргумента по ссылке - PullRequest
1 голос
/ 21 июня 2020

У меня есть функция foo с параметром int, переданным по ссылке. А у меня есть переменная с типом uint16_t. Я использую reinterpret_cast, и вот код:

#include <iostream>
#include <stdint.h>


void foo(int &bar) {
    std::cout << "bar = " << bar << std::endl;
    bar += 10;
}

int main() {
    uint16_t baz = 100;
    uint16_t qux = 200;
    foo(reinterpret_cast<int &>(baz));
    std::cout << "baz = " << baz << ", qux = " << qux << std::endl;
    foo(reinterpret_cast<int &>(qux));
    std::cout << "baz = " << baz << ", qux = " << qux << std::endl;
    return 0;
}

Результат:

bar = 100
baz = 110, qux = 200
bar = 7209160
baz = 110, qux = 210

Мои вопросы:

  1. Почему во втором при вызове foo() он печатает неправильное число, но переменная qux в конечном итоге верна?
  2. Как правильно выполнить приведение типа при вызове функции, аргумент которой передается по ссылке?

Ответы [ 3 ]

1 голос
/ 21 июня 2020
  1. В вашей функции foo, std::cout обрабатывает аргумент uint16_t как int, поэтому он читает два дополнительных байта. 200 в десятичном формате, значение qux равно 0x00C8 в шестнадцатеричном формате. Это большое длинное десятичное число 7209160 - это 0x006E00C8 в шестнадцатеричном формате. Вы видите свое значение qux в этой шестнадцатеричной строке? Начальная часть этой шестнадцатеричной строки - 0x006E, которая находится в десятичном формате 110, что означает, что std :: cout, вероятно, также захватывает переменную baz из стека, когда достигает вашей переменной qux, которая имеет только размер uint16_t; он ищет int, который в два раза больше. В конечном итоге переменная верна, потому что во второй раз, когда она передается в cout, она правильно обрабатывается как значение uint16_t.

  2. Правильный способ выполнить приведение типов в этом сценарии - это используйте static_cast, так как это приведение скажет вам, может ли оно сделать допустимое преобразование между двумя типами. В этом случае ваша компиляция не удастся. Это отличается от reinterpret_cast, который просто инструктирует компилятор обрабатывать последовательность битов как другой тип, без какого-либо учета преобразования типа.

0 голосов
/ 21 июня 2020

Ваш код имеет неопределенное поведение (UB), даже в случае foo(reinterpret_cast<int &>(baz));, который, кажется, работает (возможный вывод UB).

Проще было бы удалить приведение и изменить foo на:

void foo(int bar);

Если вы не можете изменить foo, тогда используйте промежуточную переменную:

uint16_t baz = 100;
uint16_t qux = 200;
int i = baz;
foo(i);
std::cout << "baz = " << baz << ", qux = " << qux << std::endl;
i = qux;
foo(i);
std::cout << "baz = " << baz << ", qux = " << qux << std::endl;
0 голосов
/ 21 июня 2020

каждый раз, когда программа дает одинаковые результаты? Я перевожу 200 и 7209160 в двоичную форму, и это 11001000 и 11011100000000011001000. И у них одинаковые младшие 8 бит. Таким образом, я предполагаю, есть ли ошибка при преобразовании в тип int. Это может быть правдой для использования int declare "quz".

...