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
}
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?
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
I'm translating Michael Herf's radix sort into straight C code. For positive values it works just fine, but the negative values are getting corrupted, as seen here:
Input:
-0.100000 0.100000 0.000000 0.700000 0.900000 -0.400000 -1.000000 0.200000 -0.400000 -0.700000
Expected output:
-1.000000 -0.700000 -0.400000 -0.400000 -0.100000 0.000000 0.100000 0.200000 0.700000 0.900000
Actual output:
-44.799999 -11.200000 -11.200000 -6.400000 -4.000000 0.000000 0.100000 0.200000 0.700000 0.900000
How to fix this?
Code (on Eclipse CDT, Ubuntu 16.10, compiled with GCC 6.2):
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <xmmintrin.h> // for prefetch
#define PFVAL 64
#define PFVAL2 128
#define PF(x, i) _mm_prefetch((char *)((x)+(i)+PFVAL), 0)
#define PF2(x, i) _mm_prefetch((char *)((x)+(i)+PFVAL2), 0)
#define HISTOGRAM 2048
#define HISTOGRAMS 6144 // 3*histogram
#define FLIP_FLOAT_A(x) ((x)^(((x) >> 31) | 0x80000000))
#define FLIP_FLOAT_B(x) ((x)^((((x) >> 31)-1) | 0x80000000))
// utils for accessing 11-bit quantities
#define _0(x) (x & 0x7FF)
#define _1(x) (x >> 11 & 0x7FF)
#define _2(x) (x >> 22 )
void radixsort_float(float *a, size_t num) {
uint32_t *base = (uint32_t *)a;
size_t arraysize = num*sizeof(uint32_t);
uint32_t *aux = malloc(arraysize);
uint32_t byte0[HISTOGRAMS] = { 0 };
uint32_t *byte1 = byte0+HISTOGRAM;
uint32_t *byte2 = byte1+HISTOGRAM;
// 1. parallel histogramming pass
for(size_t i = 0; i < num; ++i) {
PF(base, i);
uint32_t bi = FLIP_FLOAT_A(base[i]);
++byte0[_0(bi)];
++byte1[_1(bi)];
++byte2[_2(bi)];
}
// 2. sum the histograms: each histogram entry
// records the number of values preceding itself
uint32_t sum0 = 0, sum1 = 0, sum2 = 0;
uint32_t total;
for(size_t i = 0; i < HISTOGRAM; i++) {
total = byte0[i]+sum0;
byte0[i] = sum0-1;
sum0 = total;
total = byte1[i]+sum1;
byte1[i] = sum1-1;
sum1 = total;
total = byte2[i]+sum2;
byte2[i] = sum2-1;
sum2 = total;
}
// byte 0: floatflip entire value, read/write histogram, write out flipped
for(size_t i = 0; i < num; ++i) {
uint32_t bi = FLIP_FLOAT_A(base[i]);
uint32_t pos = _0(bi);
PF2(base, i);
aux[++byte0[pos]] = bi;
}
// byte 1: read/write histogram, copy
// aux -> array
for(size_t i = 0; i < num; ++i) {
uint32_t ai = aux[i];
uint32_t pos = _1(ai);
PF2(aux, i);
base[++byte1[pos]] = ai;
}
// byte 2: read/write histogram, copy & flip out
// base -> aux
for(size_t i = 0; i < num; ++i) {
uint32_t bi = base[i];
uint32_t pos = _2(bi);
PF2(base, i);
aux[++byte2[pos]] = FLIP_FLOAT_B(bi);
}
memcpy(base, aux, arraysize);
free(aux);
}
The problem is your FLIP_FLOAT_A macro -- it's just wrong. You need it to flip all the bits of negative numbers (not just the bottom bit), and for the macros to be the reverse of each other (so FLIP_FLOAT_B(FLIP_FLOAT_A(X)) == X for all values of X). Try:
#define FLIP_FLOAT_A(x) ((x)^(((~(x) >> 31)-1) | 0x80000000))
#define FLIP_FLOAT_B(x) ((x)^((((x) >> 31)-1) | 0x80000000))
I have a string say:
char *hexstring = "08fc0021";
this is a concatenation of two information each two bytes long.
The first two bytes of this string, ie.: 08fc corresponds to 2300 in dec.
the last 4 bytes, ie., 0021 -> 33.
My problem is to convert this string into two different variables, say:
int varA, varB;
here varA will have the number 2300, and varB = 33.
normally I would have used sscanf to convert the string into a decimal num.
but now i have this problem of a concatenated string with two different info.
any idea suggestion how to nail this ?
thx in advance
Bitwise AND to the Rescue!
So, doing what you require can be done using the bitwise AND opperator on the resulting 32bit number (int?) you get from sscanf.
You first get the number from the string:
char* hexstring = "0x08fc0021";
int num = 0;
sscanf(hexstring, "%x", &num); //put the number into num.
Then you get the bits you want using &:
int varA=0, varB=0;
varA = num & 0xFFFF; //will get the second half.
varB = num & 0xFFFF0000;
varB = varB >> 16; // now you have the first half as well.
And there you have it.
int main(int argc, char *argv[]) {
char *hexstring = "08fc0021";
unsigned long hexnumber = 0u;
unsigned short a = 0u;
unsigned short b = 0u;
/* Use sscanf() to convert the string to integer */
sscanf(hexstring, "%x", &hexnumber);
/* Use bitwise and to filter out the two higher bytes *
* and shift it 16 bits right */
a = ((hexnumber & 0xFFFF0000u) >> 16u);
/* Use bitwise AND to filter out the two lower bytes */
b = (hexnumber & 0x0000FFFFu);
printf("0x%X 0x%X\n",a,b);
return 0;
}
You can use this approach (bit operations):
char *hexstring = "08fc0021";
int aux;
sscanf(hexstring, "%x", &aux);
printf("aux = 0x%x = %d\n", aux, aux);
int varA = (aux & 0xFFFF0000) >> 16, varB = aux & 0x0000FFFF;
printf("varA = 0x%x = %d\n", varA, varA);
printf("varB = 0x%x = %d\n", varB, varB);
Result:
aux = 0x8fc0021 = 150732833
varA = 0x8fc = 2300
varB = 0x21 = 33
EDIT:
Or this approach (string manipulation):
// requires a hexstring length of 8 or more sophisticated logic
char *hexstring = "08fc0021";
int len = strlen(hexstring);
char varA[5], varB[5];
for(int i = 0; i<len; i++)
{
if(i < 4) varA[i] = hexstring[i];
else varB[i-4] = hexstring[i];
}
varA[4] = varB[4] = '\0';
int varAi, varBi;
sscanf(varA, "%x", &varAi);
sscanf(varB, "%x", &varBi);
printf("varAi = 0x%x = %d\n", varAi, varAi);
printf("varBi = 0x%x = %d\n", varBi, varBi);
Same result:
varAi = 0x8fc = 2300
varBi = 0x21 = 33
this snippet
unsigned char len_byte[4+1];
...
for(i=0; i < 4; i++) {
printf("%02x ", len_byte[i]);
}
prints
8a 00 00 00
I need now to set a integer value to 168 (0x000000a8).
Can sameone help me?
Thanks to all,
Riccardo
edit, I tried:
uint32_t len_dec=0;
len_dec += (uint32_t)len_byte[0] | ((uint32_t)len_byte[1]<<8) | ((uint32_t)len_byte[2]<<16) | ((uint32_t)len_byte[3]<<24);
printf("%" PRIu32 "\n",len_dec);
--> 4522130
With this code, I got 168 as answer :
int main(void) {
unsigned char len_byte[4] = {0x8a,0,0,0};
unsigned int len_dec = 0;
int i;
for(i = 3; i >= 0; --i)
{
len_dec |= ((len_byte[i] >> 4) << (8*i)) | ((len_byte[i] & 0xF) << ((8*i) + 4));
}
printf("%lu\n", len_dec);
return 0;
}
Tested here
The trick is to group each byte by 4 bits. 138 = 10001010 in binary. Grouping by 4 bits, you have 2 groups : 1000 and 1010. Now you swap both groups : 10101000 which gives 168. You do this action for each byte starting at the last element of the array.