user86294: Since Cpp is not my main language, I struggle to find the best way to convert between types for my needs.
So my starting point is
struct can_frame {
    canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    __u8    can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
    __u8    data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};

So first I needed it bo send to Serial as a hex string, so solution I've found and used was
String frame = "CAN:";
char dataString[1] = {0};
sprintf(dataString, "%03X", can1Msg.can_id);
frame += dataString;
for (int i = 0; i < can1Msg.can_dlc; i++) {  // print the data
  char dataString[1] = {0};
  sprintf(dataString, "%02X", can1Msg.data[i]);
  frame += " " + String(dataString);
}

Doesn't seem elegant byt it did the job.
But then I needed to do some checking of ID and specific bytes
So I've saved all String ins String bytes[8]
So  now I could something like
if (id == "2A0" && bytes[0] == "A0") {

And that was almost over, but then I realized that I need to do some checking of Integer number that is saved on 3 bytes.
E.G byte[2] + byte[3] + byte[4] which would something like 0020A0 whih will be 8352 as an Int
But converting things around gave all the problems such us String to const char* etc.
I wanted to convert __u8 to byte array so I can do checks and conversions and eventually convert it to string, but I've failed.
Can anyone suggest best approach for this ?

user4143: The main problem that you are having is a lack of understanding in what "hex", "byte", etc are.
You are trying to work with four data types (int, hex, string and byte) when in reality there are only two types: String and binary. Everything else is just a representation we as humans use to make easier sense of the binary data.
You have a "source" type (can1Msg.data) which is, at one and the same time, binary, integer, hex and byte. The only thing it is not is String and you create that manually with your sprintf calls.
To compare the third "hex pair" value in your data you simply:
if (can1Msg.data[2] == 0x42) { ...

That is, compare the 8-bit binary value stored in array slice 2 (arrays count from 0 so 2 is the third entry) with the binary value represented by the hex notation 42.  The exact same thing can be done with:
if (can1Msg.data[2] == 66) { ...

66 is the decimal (base 10) equivalent of 0x42.  You can also use binary or octal. These two are also exactly the same:
if (can1Msg.data[2] == 0102) { ... // octal
if (can1Msg.data[2] == 0b01000010) { ... // binary

If you need to examine groups of bytes, such as if you have two bytes that form a 16-bit integer, you simply combine those two bytes into an integer, taking care to obey the correct endianness of the values.  For example if you have a 16 bit integer that is stored as can1Msg.data[7] and can1Msg.data[8] in big endian form, you can use:
uint16_t val = (can1Msg.data[7] << 8) | can1Msg.data[8];

Then simply compare the numeric (binary) integer value at will.  All that line does is take the first 8 bit value and "shift" it 8 bits to the left to make it a 16 bit value with the lower 8 bits set to 0, then overlay the second value over those lower 8 zeroes, to make it a single 16-bit value.

86294: <p>Since Cpp is not my main language, I struggle to find the best way to convert between types for my needs.
So my starting point is</p>
<pre class="lang-cpp prettyprint-override"><code>struct can_frame {
    canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    __u8    can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
    __u8    data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};
</code></pre>
<p>So first I needed it bo send to Serial as a hex string, so solution I've found and used was</p>
<pre class="lang-cpp prettyprint-override"><code>String frame = &quot;CAN:&quot;;
char dataString[1] = {0};
sprintf(dataString, &quot;%03X&quot;, can1Msg.can_id);
frame += dataString;
for (int i = 0; i &lt; can1Msg.can_dlc; i++) {  // print the data
  char dataString[1] = {0};
  sprintf(dataString, &quot;%02X&quot;, can1Msg.data[i]);
  frame += &quot; &quot; + String(dataString);
}
</code></pre>
<p>Doesn't seem elegant byt it did the job.</p>
<p>But then I needed to do some checking of ID and specific bytes
So I've saved all String ins <code>String bytes[8]</code>
So  now I could something like</p>
<pre class="lang-cpp prettyprint-override"><code>if (id == &quot;2A0&quot; &amp;&amp; bytes[0] == &quot;A0&quot;) {
</code></pre>
<p>And that was almost over, but then I realized that I need to do some checking of Integer number that is saved on 3 bytes.
E.G <code>byte[2] + byte[3] + byte[4]</code> which would something like <code>0020A0</code> whih will be <code>8352</code> as an Int</p>
<p>But converting things around gave all the problems such us <code>String to const char*</code> etc.
I wanted to convert <code>__u8</code> to byte array so I can do checks and conversions and eventually convert it to string, but I've failed.
Can anyone suggest best approach for this ?</p>
 4143: <p>The main problem that you are having is a lack of understanding in what &quot;hex&quot;, &quot;byte&quot;, etc are.</p>
<p>You are trying to work with four data types (int, hex, string and byte) when in reality there are only two types: String and binary. Everything else is just a representation we as humans use to make easier sense of the binary data.</p>
<p>You have a &quot;source&quot; type (<code>can1Msg.data</code>) which is, at one and the same time, binary, integer, hex and byte. The only thing it is not is <code>String</code> and you create that manually with your <code>sprintf</code> calls.</p>
<p>To compare the third &quot;hex pair&quot; value in your data you simply:</p>
<pre class="lang-cpp prettyprint-override"><code>if (can1Msg.data[2] == 0x42) { ...
</code></pre>
<p>That is, compare the 8-bit binary value stored in array slice 2 (arrays count from 0 so 2 is the third entry) with the binary value represented by the hex notation 42.  The exact same thing can be done with:</p>
<pre class="lang-cpp prettyprint-override"><code>if (can1Msg.data[2] == 66) { ...
</code></pre>
<p>66 is the decimal (base 10) equivalent of 0x42.  You can also use binary or octal. These two are also exactly the same:</p>
<pre class="lang-cpp prettyprint-override"><code>if (can1Msg.data[2] == 0102) { ... // octal
if (can1Msg.data[2] == 0b01000010) { ... // binary
</code></pre>
<p>If you need to examine groups of bytes, such as if you have two bytes that form a 16-bit integer, you simply combine those two bytes into an integer, taking care to obey the correct <a href="https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/" rel="nofollow noreferrer">endianness</a> of the values.  For example if you have a 16 bit integer that is stored as <code>can1Msg.data[7]</code> and <code>can1Msg.data[8]</code> in <em>big endian</em> form, you can use:</p>
<pre class="lang-cpp prettyprint-override"><code>uint16_t val = (can1Msg.data[7] &lt;&lt; 8) | can1Msg.data[8];
</code></pre>
<p>Then simply compare the numeric (binary) integer value at will.  All that line does is take the first 8 bit value and &quot;shift&quot; it 8 bits to the left to make it a 16 bit value with the lower 8 bits set to 0, then overlay the second value over those lower 8 zeroes, to make it a single 16-bit value.</p>
