0

I have a problem I have an Hexadecimal like 0x6002 and I have to split it into 0x60 and 0x02. how do I do that?

I progam in cpp and have to communicate with a network port. For that I have an address which I have to split in the middle my issue is that I store the hex in a Uint8 wich converts the number to a decimal. how can i solve my problem?

Akira
  • 4,385
  • 3
  • 24
  • 46
FerusOlin
  • 3
  • 1
  • 3

3 Answers3

4

You can use masking to extract the low byte and a shift to extract the high byte:

uint16_t a = 0x6002;
uint8_t a0 = a & 0xff;  // a0 = 0x02
uint8_t a1 = a >> 8;    // a1 = 0x60

Note that the & 0xff is not strictly necessary for a narrowing unsigned conversion such as that above, but there are other cases where it might be necessary (e.g. when signed conversion is involved, or when the destination type is wider than 8 bits), so I'll leave it in for illustrative purposes.

Paul R
  • 208,748
  • 37
  • 389
  • 560
2
uint16_t port = 0x6002;
uint8_t high = (port >> 8) & 0xFF;
uint8_t low = port & 0xFF;
Michael Smith
  • 1,271
  • 1
  • 8
  • 31
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    No +1 for not using the standard (!!) specified-width types. ;-) – DevSolar Sep 12 '14 at 15:28
  • I was going off of what the OP said he was using. Not every compiler has `uintX_t` available. Or maybe he's using an API that has its own typedefs. I didn't want to make any assumptions. – Remy Lebeau Sep 12 '14 at 15:50
2

Pointers are MUCH FASTER than shifts and require no processor math. You create your 2 byte variable and use Pointers to change each byte separately.

Here is an example:

uint16_t myInt; // 2 byte variable

uint8_t *LowByte = (uint8_t*)myInt; // Point LowByte to the same memory address as
              // myInt, but as a uint8 (1 byte) instead of a uint16 (2 bytes)
              // Note that low bytes come first in memory


uint8_t *HighByte = (uint8_t*)myInt + 1; // 1 byte offset from myInt start
// which works the same way as:
uint8_t *HighByte = LowByte + 1; // 1 byte offset from LowByte

In some compilers the pointer syntax is a little different (such as Microsoft C++):

uint16_t myInt; // 2 byte variable

uint8_t *LowByte = (uint8_t*)&myInt; // Point LowByte to the same memory address as
              // myInt, but as a uint8 (1 byte) instead of a uint16 (2 bytes)
              // Note that low bytes come first in memory

uint8_t *HighByte = (uint8_t*)&myInt + 1; // 1 byte offset from myInt start

The * char in type definition indicates you are creating a pointer, not a variable. The pointer points to a memory address instead of it´s value. To write or read the value of the variable pointed to, you add * to the variable name.

So, to manipulate the full 2 bytes together, or separately, here are some examples:

myInt = 0x1234; // write 0x1234 to full int

*LowByte = 0x34; // write 0x34 to low byte

*HighByte = 0x12; // write 0x12 to high byte


uint8_t x = *LowByte; // read low byte

uint8_t y = *HighByte; // read high byte

uint16_t z = myInt; // reads full int
cyberponk
  • 1,585
  • 18
  • 19
  • Does it work well on any platform? Does the endianness change the way it's stored in memory? – cube45 Jun 27 '17 at 09:42
  • Should work on any platform. I have personally used this in many platforms (from turbo c to arduino) with success. If by some reason your platform stores the bytes inverted (which I have never seen), you can simply invert the pointers' addresses or names, so it should be an easy fix. This was tought to me in university so it is not a 'hack'. – cyberponk Jun 27 '17 at 17:06
  • This should work well on many of the major platforms. I don't know about ARM processors like the raspberry pi : https://en.wikipedia.org/wiki/Endianness#Current_architectures – cube45 Jun 28 '17 at 12:35
  • Are you really sure this is faster than bitshifts? Size of pointers can be differnt than 32bit. Int can be other than 32bit! Also this approach stinks for access violations on any OS. You also mix signed and unsigned this should crash on compiler flags you should use treat warnings as errors and enable all debug flags for productive code. You really should do that in your code. Warnings in C/C++ should not be ignored! – akira hinoshiro May 07 '20 at 13:46
  • Yes this is much faster than shifts, you can test it yourself in any debugger that couns processor ticks. – cyberponk May 07 '20 at 15:18
  • You are correct on the pointer size comment, although this answer was specific for the OPs question. I have changed the answer for a more generic approach. As far as I am concerned, pointers should not tick warnings because they are accessing memory directly instead of using compiler variables. Thanks – cyberponk May 07 '20 at 15:28