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.
Related
I know that an unsigned character's size is 8 bits, and the size of an integer is 32 bits.
But I want to know if I perform an operation between two integers below 255, is it safe to say it is as fast as performing the same operation on two unsigned characters of the same value of that integers?
Example:
int Int2 = 0x10;
int Int1 = 0xff;
unsigned char Char0 = 0x10;
unsigned char Char1 = 0xff;
Int1 + Int2 ; // Is calculating this
Char0 + Char1; // Faster than this??
Update:
Let's put this in the context as someone suggested
for (unsigned char c=0;c!=256;c++){ // does this loop
std::cout<<c; // dont mind this line it can be any statement
}
for (int i=0;i!=256;i++){ // perform faster than this one??
std::cout<<i;// this too
}
I know that an unsigned character's size is 8 bits
This is not necessarily always the case in C++. But it may be true in particular implementation of C++.
and the size of an integer is 32 bits.
There are several integer types in C++. In fact, character types are integer types as well.
Int1 + Int2 ; // Is calculating this
Char0 + Char1; // Faster than this??
Integers of lower rank than int are promoted to int (or unsigned int in rare cases) when used as operand of most binary operators. Both operators in the example operate on int after the promotion. You don't use the result at all, so there's no need for the compiler to produce any code, so they should be equally fast in this trivial example.
Whether one piece of code is faster than the other depends on many factors. It's not possible to accurately guess which way it would go without context.
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.
I'm programming with a PLC and I'm reading values out of it.
It gives me the data in unsigned char. That's fine, but the values in my PLC can be over 255. And since unsigned chars can't give a value over 255 I get the wrong information.
The structure I get from the library:
struct PlcVarValue
{
unsigned long ulTimeStamp ALIGNATTRIB;
unsigned char bQuality ALIGNATTRIB;
unsigned char byData[1] ALIGNATTRIB;
};
ulTimeStamp gives the time
bQuality gives true/false (be able to read it or not)
byData[1] gives the data.
Anyways I'm trying this now: (where ppValues is an object of PlcVarValue)
unsigned char* variableValue = ppValues[0]->byData;
int iVariableValue = *variableValue;
This works fine... untill ppValues[0]->byData is > 255;
When I try the following when the number is for example 257:
unsigned char testValue = ppValues[0]->byData[0];
unsigned char testValue2 = ppValues[0]->byData[1];
the output is testvalue = 1 and testvalue2 = 1
that doesn't make sense to me.
So my question is, how can I get this solved so it gives me the correct number?
That actually looks like a variable-sized structure, where having an array of size 1 at the end being a common way to have it. See e.g. this tutorial about it.
In this case, both bytes being 1 for the value 257 is the correct values. Think of the two bytes as a 16-bit value, and combine the bits. One byte will become the hight byte, where 1 corresponds to 256, and then add the low bytes which is 1 and you have 256 + 1 which of course is equal to 257. Simple binary arithmetic.
Which byte is the high, and which is the low we can't say, but it's easy to check if you can force a message that contains the value 258 instead, as then one byte will still be 1 but the other will be 2.
How to combine it into a single unsigned 16-bit value is also easy if you know the bitwise shift and or operators:
uint8_t high_byte = ...
uint8_t low_byte = ...
uint16_t word = high_byte << 8 | low_byte;
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.
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.