Fastest convesion from uint8 to hex char - c++

Suppose I have an 1-byte wide integer (where only the lower 4 bits are actually active) and I want to convert it to its hex value as a char.
uint8_t original_int = 0xF; // will always be 0x0 to 0xF
char converted_int = // something that doesnt require a string to use the std library
// yet is still portable. i'd just like to use 1 char

char converted_int =
original_int < 0xA ?
('0' + original_int) :
('A' + original_int - 0xA);
This one is memory-efficient. With pipeline execution, I think it is fast enough.

Anything wrong with this?
uint8_t original_int = 0xF;
char converted_int = "0123456789ABCDEF"[original_int];
Using a string literal as your look up table is a bit funky. But however it's done a look up table is the way to go.

Related

How to add the hex values of two or more chars?

I am storing some hex values inside a char array. I would like to sum these hex values and if it is bigger than 1 byte then it should drop the larger bits.
For example I might declare
char a = 0x21;
char b = 0x07;
and so I would like to add them to get a hex value of 0x28 as it should be, which is stored as a char.
Thanks tkausl. It made me realise the answer will be in int type, and I was confused why it gave me 40.
I was looking for char(a+b).

Converting 2 chars to its ascii binary code

I'm reading binary data in character format from an accelerometer and it consists of higher byte and lower byte. It's a long time since I worked with C++ and usually only used higher level stuff.
I have the following function:
short char2short(char* hchar, char* lchar)
{
char temp[2];
temp[0] = *hchar;
temp[1] = *lchar;
How can I get that values converted to an integer?
atoi works different as far as I know (e.g. "21" = 21).
Can I just typecast char to int? But how does it work with higher bit and lower bit?
Thanks in advance for any help!
You should store the bytes as unsigned to avoid issues with shifting sign bits.
short char2short(unsigned char hchar, unsigned char lchar)
{
return static_cast<short>(lchar | (hchar << 8));
}
You may also want to use unsigned short. It depends what you expect.

BCD Calculator issue

I am converting a hex 0xE0 to BCD. When I do this I am getting back a 64. I know this is completely wrong and maybe it's something in my C++ code, but 64 just doesn't sound correct. Any ideas? Is 0xE0 a special case? (0xE0 is 224 in decimal.)
Here is part of my code:
unsigned char Hex2BCD(unsigned char param)
{ unsigned char lo;
unsigned char hi;
unsigned char val;
unsigned char buf[10];
hi = param/ 10;
lo = param- (hi * 10);
val= (hi << 4) + lo;
return val;
}
my idea is that your code for converting to BCD is buggy. it does not do what it is supposed to, thus the wrong result you are observing.
aside from this joke: 0xe0 if stored in signed char is a negative number. that could play nasty tricks on you if you don't pay special attention on the sign of temporary variables you are using while computing the result.
edit: now that you posted some code, it is clear that, although you compute the right value for the first digit into lo, you need another step in order to get the right value into hi.
using 0xe0 as input, you are actually computing (22<<4) + 4 = 356 = 0x164 instead of (2<<8)+(2<<4)+4 = 548 = 0x224.

C++ any hex to char

Is there a better way from hex to char?
char one = static_cast<char>(0x01);
(asking because of this --> C++ using pointers, nothing is passed )
Also is there a fast way to make a char array out of hex values (eg. 0x12345678 to a char array)?
You can try this:
std::string hexify(unsigned int n)
{
std::string res;
do
{
res += "0123456789ABCDEF"[n % 16];
n >>= 4;
} while(n);
return std::string(res.rbegin(), res.rend());
}
Credits to STL for the "index into char array" trick.
Also beware when printing chars, which are signed on some platforms. If you want 128 to print as 80 rather than FFFFFFFF, you have to prevent it from being treated as -1 by converting to unsigned char first: hexify((unsigned char)(c));
What do you intend to be stored in the variable one?
The code as written will store the ASCII character 0x01 into one. This is a control character, not a printable character. If you're looking for the digit 1, then you need to say so explicitly:
char one = '1';
That stores the actual character, not the ASCII code 0x01.
If you are trying to convert a number into the string representation of that number, then you need to use one of these mechanisms. If instead, you are trying to treat a 32-bit integer as a sequence of 4 bytes, each of which is an ASCII character, that is a different matter. For that, you could do this:
uint32_t someNumber = 0x12345678;
std::string myString(4, ' ');
myString[0] = static_cast<char>((someNumber >> 24) & 0xFF);
myString[1] = static_cast<char>((someNumber >> 16) & 0xFF);
myString[2] = static_cast<char>((someNumber >> 8) & 0xFF);
myString[3] = static_cast<char>((someNumber) & 0xFF);

Bit Operators to append two unsigned char in C++

If I have two things which are hex, can I someone how append their binary together to get a value?
In C++,
say I have
unsigned char t = 0xc2; // 11000010
unsigned char q = 0xa3; // 10100011
What I want is somehow,
1100001010100011, is this possible using bit-wise operators?
I want to extract the binary form of t and q and append them...
Yes it's possible.
Just use the left-bitshift operator, shifting to the left by 8, using at least a 16-bit integer. Then binary OR the 2nd value to the integer.
unsigned char t = 0xc2; // 11000010
unsigned char q = 0xa3; // 10100011
unsigned short s = (((unsigned short)t)<<8) | q; //// 11000010 10100011
Alternatively putting both values in a union containing 2 chars (careful of big endian or small) would have the same bit level result. Another option is a char[2].
Concatenating two chars:
unsigned char t = 0xc2; // 11000010
unsigned char q = 0xa3; // 10100011
int result = t; // Put into object that can hold the fully concatenated data;
result <<= 8; // Shift it left
result |= q; // Or the bottom bits into place;
Your example doesn't really work too well because the width (usually 8-bits) of the input values aren't defined. For example, why isn't your example: 0000000100000010, which would be truly appending 1 (00000001) and 2 (00000010) bit wise.
If each value does have a fixed width then it can be answered with bit shifting and ORing values
EDIT: if your "width" is defined the full width with all leading zero's removed, then it is possible to do with shifting and ORing, but more complicated.
I'd go with the char array.
unsigned short s;
char * sPtr = &s;
sPtr[0] = t; sPtr[1] = q;
This doesn't really care about endian..
I'm not sure why you'd want to do this but this would work.
The problem with the bit methods are that you're not sure what size you've got.
If you know the size.. I'd go with Brians answer
There is no append in binary/hex because you are dealing with Numbers (can you append 1 and 2 and not confuse the resulting 12 with the "real" 12?)
You could delimit them with some special symbol, but you can't just "concatenate" them.
Appending as an operation doesn't really make sense for numbers, regardless of what base they're in. Using . as the concatenation operator: in your example, 0x1 . 0x2 becomes 0x12 if you concat the hex, and 0b101 if you concat the binary. But 0x12 and 0b101 aren't the same value (in base 10, they're 18 and 5 respectively). In general, A O B (where A and B are numbers and O is an operator) should result in the same value no matter what base you're operating in.