Simple addition is not suitable to "combine" two characters, you won't ever be able to determine from 22 if it has been composed of 10 and 12, 11 and 11, 7 and 15 or any other combination; additionally, if order is relevant, you won't ever know if it has been 10 and 12 or 12 and 10...
Now you can combine your values in an array or std::string
(if representing arbitrary 8-bit-data, you might even prefer std::array
or std::vector
). Another variant is doing some nice math:
combined = x * SomeFactorLargerThanAnyPossibleChar + y;
Now you can get your two values back via division and modulo calculation.
Assuming you want to encode ASCII only, 128 is sufficient; considering maximum values, you get: 127*128+127 == 127*129 == 2^14 - 1
. You might see the problem with yourself, though: Results might need up to 14 bit, so your results won't fit into a simple char any more (at least on typical modern hardware, where char normally has eight bits only – there are systems around, though, with char having 16 bits...).
So you need a bigger data type for:
uint16_t combined = x * 128U + y;
//^^
Side note: if you use 256 instead, each of x and y will be placed into separate bytes of the two of uint16_t. On the other hand, if you use uint64_t and 127 as factor, you can combine up to 9 ASCII characters in one single data type. In any case, you should always use powers of two so your multiplications and divisions can be implemented as bitshifts and the modulo calculations as simple AND-operation with some appropriate mask.
Care has to be taken if you use non-ASCII characters as well: char might be signed, so to prevent unwanted effects resulting from sign extension when values being promoted to int, you need to yet apply a cast:
uint16_t combined = static_cast<uint8_t>(x) * 128U + static_cast<uint8_t>(y);