I have a 4 text-represented bytes that i need to divide into 2 bytes (HI and LO byte) and convert it to two integers.
How can i do that in plain C?
0x4b 0xab 0x14 0x9d
By text i mean that they look like "0x4b" not 0x4b.
I already have those string splited into char array, which represents like this:
item[0] = "0x4b";
item[1] = "0xab";
item[2] = "0x14";
item[3] = "0x9d";
Now the finish should look like this:
0x4b 0xab - one integer
0x14 0x9d - second integer
How to do this in Plain C?
You probbaly want this:
#include <stdlib.h>
#include <stdio.h>
int main()
{
char *item[4];
item[0] = "0x4b";
item[1] = "0xab";
item[2] = "0x14";
item[3] = "0x9d";
int value1 = (strtol(item[0], NULL, 0) << 8) | strtol(item[1], NULL, 0);
int value2 = (strtol(item[2], NULL, 0) << 8) | strtol(item[3], NULL, 0);
printf("%x %x", value1, value2);
}
This is another approach if you need intermediate results:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void)
{
int item1[4];
int item2[2];
char *item[4];
item[0] = "0x4b";
item[1] = "0xab";
item[2] = "0x14";
item[3] = "0x9d";
for (int i = 0; i < 4; i++)
{
item1[i] = strtol ( item[i], NULL, 0 ) ;
printf("%2X\n", item1[i]);
}
for (int i = 0; i < 2; i++)
{
item2[2*i] = (item1[2*i] << 8) | item1[2*i+1];
printf("Received integers: %2X\n", item2[2*i]);
}
return 0;
}
Output:
4B
AB
14
9D
Received integers: 4BAB
Received integers: 149D
Related
I'm trying to implement LEB128 to write a custom Minecraft Server implemention. I'm doing so by following Wikipedia article about LEB128 and port example Javascript code given to C.
https://en.wikipedia.org/wiki/LEB128
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int leb128(const char* in) {
int result = 0;
int shift_counter = 0;
size_t s = strlen(in);
int data = atoi(in);
for(unsigned char i = 0; i < s; i++) {
const char byte = ((unsigned char*)&data)[i];
result |= (byte & 0x7f) << i * 7;
shift_counter += 7;
if(!(byte & 0x80)) break;
if((shift_counter < 32 && (byte & 0x40)) != 0) return result |= (~0 << shift_counter);
}
return result;
}
/* this actually prints bytes makes the int but lazily named it because I renamed every function i took from my og project to avoid revealing the name */
void printInt(int a) {
int* e = &a;
puts("\n");
for(unsigned i = 0; i < sizeof(int); i++) {
printf(" %d ", ((unsigned char*)e)[i]);
}
}
int main(void) {
printInt(leb128("-1"));
printInt(leb128("255"));
printInt(leb128("25565"));
return 0;
}
problem is that I do not receive data in given example table located at https://wiki.vg/Protocol
screenshot from wiki.vg
Input
Expected
Output
-1
255 255 255 15
255 255 255 255
255
255 1
255 255 255 255
25565
221 199 1
221 255 255 255
What could be I'm doing wrong?
How can I convert a string decimal to hex decimal and add them to char pointer? Why does the memcpy(value + 2, &value_value, value_length); not work, the result is 0x02 0x01 and not 0x02 0x01 0x4f.
#include <string.h> /* strlen */
#include <stdio.h> /* printf */
#include <stdint.h> /* int32_t */
#include <stdlib.h> /* strtol */
int main()
{
char value_type = 0x02;
char *value_value = "79"; /* Must convert to 4f */
char value_length;
int32_t num = strtol(value_value, NULL, 10);
if (num < 255)
value_length = 0x01;
else if (num < 65536)
value_length = 0x02;
else if (num < 16777216)
value_length = 0x03;
else if (num < 4294967295)
value_length = 0x04;
char *value = malloc(2 + value_length);
memcpy(value, &value_type, 1);
memcpy(value + 1, &value_length, 1);
memcpy(value + 2, &value_value, value_length);
/* expectation: 0x02 0x01 0x4f */
for (int i = 0; i < strlen(value); i++)
printf("%02x\n", value[i]);
return 0;
}
memcpy(value + 2, &value_value, value_length);
this expression copies value_length bytes from &value_value.
Given that it's declared as
char *value_value
&value_value is read as a pointer-to-a-pointer-to-a-char. So effectively you're reading the pointer value.
How to solve:
memcpy(value + 2, &num, value_length);
Another problem with your code:
you're using strlen(value) while value is not a null-terminated C-string. It's just an array of bytes that you fill with your data.
How to fix:
don't use strlen in this case, you know the size of the array: 2 + value_length. For clarity you may put it to a separate variable.
You are using wrong variable:
memcpy(value + 2, &num, value_length);
Also, you must not trait your value as string, as far as it uses binary value. Change your code to:
/* expectation: 0x02 0x01 0x4f */
int dumplen=len+2;
for (int i = 0; i < dumplen; i++)
printf("%02x\n", value[i]);
return 0;
I have a byte array of 6 elements which contains the MAC address of a WiFi chip. How do I convert this into a single value. For e.g. If the array is:
mac[0] = 208
mac[1] = 181
mac[2] = 194
mac[3] = 193
mac[4] = 114
mac[5] = 219
How do I get a value like this: 208181194193114219 which in representation is essentially all the digits concatenated.
I tried AND'ing the individual mac IDs with 0xFFh and then bit-shifted them to the left but I see a value of 3250763216. This is the code:
uint32_t deviceID = 0;
for (int i = 0; i < 6; i++)
{
deviceID += (mac[i] & 0xFFh) << (8 * i);
}
Serial.print("Device ID : "); Serial.println(deviceID);
You can do this:
#include <iostream>
#include <sstream>
int main() {
std::stringstream ss;
int mac[] = {208,181,194,193,114,219};
for (unsigned i = 0; i < sizeof mac / sizeof mac[0]; ++i)
ss << mac [i];
int result;
ss >> result;
std::cout << result; //208181194193114219
}
I have a string for which I compute a sha1 digest like this:
SHA1(sn, snLength, sha1Bin);
If I'm correct this results in a 20 byte char (with binary data). I want to compare the last 3 bytes of this char with another char. This char contains the string "6451E6". 64, 51 & E6 are hex values. How do I convert "6451E6" so that I can compare it via:
if(memcmp(&sha1Bin[(20 - 3)], theVarWithHexValues, 3) == 0)
{
}
I have this function:
/*
* convert hexadecimal ssid string to binary
* return 0 on error or binary length of string
*
*/
u32 str2ssid(u8 ssid[],u8 *str) {
u8 *p,*q = ssid;
u32 len = strlen(str);
if( (len % 2) || (len > MAX_SSID_OCTETS) )
return(0);
for(p = str;(*p = toupper(*p)) && (strchr(hexTable,*p)) != 0;) {
if(--len % 2) {
*q = ((u8*)strchr(hexTable,*p++) - hexTable);
*q <<= 4;
} else {
*q++ |= ((u8*)strchr(hexTable,*p++) - hexTable);
}
}
return( (len) ? 0 : (p - str) / 2);
}
which does the same but I'm new to C and don't understand it :-(
It's easier to go the other way — convert the binary data to a hex string for comparison:
char suffix[7];
sprintf(suffix, "%02x%02x%02x", sha1Bin[17], sha1Bin[18], sha1Bin[19]);
return stricmp(suffix, theVarWithHexValues) == 0;
Even if you prefer converting to binary, sscanf(...%2x...) is better than manually parsing hex numbers.
Fix for AShelly's code:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int hashequal(const unsigned char *sha1Bin, const char *hexstr) {
unsigned long hexvar = strtoul(hexstr, NULL, 16);
unsigned char theVarWithHexValues[] = { hexvar >> 16, hexvar >> 8, hexvar };
return memcmp(sha1Bin + 17, theVarWithHexValues, 3) == 0;
}
int main() {
unsigned char sha1Bin[20];
sha1Bin[17] = 0x64;
sha1Bin[18] = 0x51;
sha1Bin[19] = 0xE6;
printf("%d\n", hashequal(sha1Bin, "6451E6"));
printf("%d\n", hashequal(sha1Bin, "6451E7"));
}
If theVarWithHexValues is indeed a constant of some sort, then the easiest thing would be to put it into binary form directly. Instead of:
const char *theVarWithHexValues = "6451E6";
use:
const char *theVarWithHexValues = "\x64\x51\xE6";
...then you can just memcmp() directly.
char* hexstr = "6451E6";
unsigned long hexvar = strtoul(hexstr, NULL, 16);
hexvar = htonl(hexvar)<<8; //convert to big-endian and get rid of zero byte.
memcmp(&sha1Bin[(20 - 3)], (char*)hexvar, 3)
what i mean is that if i want to store for example 11110011 i want to store it in exactly 1 byte in memory not in array of chars.
example:
if i write 10001111 as an input while scanf is used it only get the first 1 and store it in the variable while what i want is to get the whole value into the variable of type char just to consume only one byte of memory.
One way to write that down would be something like this:
unsigned char b = 1 << 7 |
1 << 6 |
1 << 5 |
1 << 4 |
0 << 3 |
0 << 2 |
1 << 1 |
1 << 0;
Here's a snippet to read it from a string:
int i;
char num[8] = "11110011";
unsigned char result = 0;
for ( i = 0; i < 8; ++i )
result |= (num[i] == '1') << (7 - i);
like this....
unsigned char mybyte = 0xF3;
Using a "bit field"?
#include <stdio.h>
union u {
struct {
int a:1;
int b:1;
int c:1;
int d:1;
int e:1;
int f:1;
int g:1;
int h:1;
};
char ch;
};
int main()
{
union u info;
info.a = 1; // low-bit
info.b = 1;
info.c = 0;
info.d = 0;
info.e = 1;
info.f = 1;
info.g = 1;
info.h = 1; // high-bit
printf("%d %x\n", (int)(unsigned char)info.ch, (int)(unsigned char)info.ch);
}
You need to calculate the number and then just store it in a char.
If you know how binary works this should be easy for you. I dont know how you have the binary data stored, but if its in a string, you need to go through it and for each 1 add the appropriate power of two to a temp variable (initialized to zero at first). This will yield you the number after you go through the whole array.
Look here: http://www.gidnetwork.com/b-44.html
Use an unsigned char and then store the value in it. Simple?
If you have read it from a file and it is in the form of a string then something like this should work:
char str[] = "11110011";
unsigned char number = 0;
for(int i=7; i>=0; i--)
{
unsigned char temp = 1;
if (str[i] == '1')
{
temp <<= (7-i);
number |= temp;
}
}