Alexander Zhang
Alexander Zhang

Reputation: 207

C++ type casting when passing argument by reference

I have a function foo with an int parameter passed by reference. And I have a variable with uint16_t type. I use reinterpret_cast and here is the code:

#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;
}

The output is:

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

My questions are:

  1. Why in the 2nd time calling foo(), it prints a wrong number, but variable qux is eventually correct?
  2. What's the correct way to do a type casting when calling a function whose argument is passed by reference?

Upvotes: 1

Views: 2942

Answers (3)

Jarod42
Jarod42

Reputation: 217448

Your code has undefined behavior (UB), even in the case foo(reinterpret_cast<int &>(baz)); which seems to works (possible output of UB).

Simpler would be to remove cast and change foo to:

void foo(int bar);

If you cannot change foo, then, use intermediate variable:

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;

Upvotes: 1

Kellen Cataldo
Kellen Cataldo

Reputation: 53

  1. In your function foo, std::cout is treating a uint16_t argument as an int so it is reading two extra bytes. 200 in decimal, the value of qux is 0x00C8 in hexadecimal. That big long decimal number 7209160 is 0x006E00C8 in hexadecimal. Do you see your qux value in that hex string? The leading part of that hex string is 0x006E which is in decimal 110, meaning that std::cout is probably also grabbing the baz variable off the stack when it reaches for your qux variable which is only of size uint16_t; it is looking for an int, which is twice that size. The variable is eventually correct because the second time it is passed to cout, it is being correctly treated as a uint16_t value.

  2. The correct way to do type-casting in this scenario is to use static_cast as this cast will tell you if it can make a valid conversion between the two types. In this case, your compilation would fail. This is in contrast to reinterpret_cast which simply instructs the compiler to treat a sequence of bits as a different type, without any consideration given to type conversion.

Upvotes: 2

Jason_AnN
Jason_AnN

Reputation: 109

every time the program has the same results? I translate the 200 and 7209160 to binary, and they are 11001000 and 11011100000000011001000. And they have same low 8 bits. Thus i guess whether it convert to type int has error. This can be verity to use int declare "quz".

Upvotes: 1

Related Questions