How to convert byte array (containing hex values) to decimal - c

I am writing some code for an Atmel micro-controller. I am getting some data via Uart, and I store these hex values into an array.
Suppose the elements of the array are: 1F, 29, and 3C.
I want to have one hex number like 0x1F293C, and convert it to a decimal number. So, I want to get “2042172” at the end.
The array could have n elements, so I need a general solution.
Thank you.

sprintf(buffer, "%d", (((unsigned)array[0])<<16)+(((unsigned)array[1])<<8)+(unsigned)array[2];
this will write the hex values in array to buffer as readable string in decimal representation.
assuming sizeof(int)=4

If you have a array of characters like "0x1F293C" and want to convert it to int try this code:
char receivedByte[] = "0x1F293C";
char *p;
int intNumber = strtol(receivedByte, &p, 16);
printf("The received number is: %ld.\n", intNumber);

If data is declared as stated in the comments (char data[]={0x1F, 0x29, 0x3C}), you can run this program.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char receivedByte[9], *p;
char data[] = { 0x1F, 0x29, 0x3C };
sprintf(receivedByte, "0x%X%X%X", data[0], data[1], data[2]);
int intNumber = strtol(receivedByte, &p, 16);
printf("The received number is: %ld.\n", intNumber);
return 0;
}

If the input consists of n bytes and are stored starting from a pointer array, you can add the values up in the order you "received" them - i.e., in the order they are written in the array.
unsigned int convertToDecimal (unsigned char *array, int n)
{
unsigned int result = 0;
while (n--)
{
result <<= 8;
result += *array;
array++;
}
return result;
}
Note that your sample input contains 3 bytes and you want a "general solution for n bytes", and so you may run out of space really fast. This function will only work for 0..4 bytes. If you need more bytes, you can switch to long long (8 bytes, currently).
For longer sequences than that you need to switch to a BigNum library.

#include <stdio.h>
int main(){
char data[] = {0x1F, 0x29, 0x3C};
int i, size = sizeof(data);
unsigned value = 0;
for(i=0;i<size;++i)
value = value * 256 + (unsigned char)data[i];
printf("0x%X %d\n", value, (int)value);
return 0;
}

Related

Recoding printf %p with write function, no printf

I am currently working on a task where I need to print the address of a variable. It would be easy to use printf %p but I am only allowed to use write from unistd.
I tried casting the pointer in to an unsigned integer and uintptr_t and then converting it into a hexadecimal number. With uintptr_t it works but with an unsigned integer it only prints half of the address. Maybe someone can explain me why this is the case?
I also saw some solutions using ">>" and "<<" but I didn't get why that works. It would be nice if someone can explain a solution using "<<" and ">>" step by step, because I am not sure if I am allowed to use uintptr_t.
this is the code I use to cast it into a unsigned int / unitptr_t / unsigned long long (I know that ft_rec_hex is missing leading 0's):
void ft_rec_hex(unsigned long long nbr)
{
char tmp;
if (nbr != 0)
{
ft_rec_hex(nbr / 16);
if (nbr % 16 < 10)
tmp = nbr % 16 + '0';
else
tmp = (nbr % 16) - 10 + 'a';
write(1, &tmp, 1);
}
}
int main(void)
{
char c = 'd';
unsigned long long ui = (unsigned long long)&c;
ft_rec_hex(ui);
}
It looks like only half of the address is printed because the "unsigned integer" you used has only half size of uintptr_t. (note that uintptr_t is an unsigned integer type)
You can use an array of unsigned char to store data in a pointer variable and print that to print full pointer withput uintptr_t.
Using character types to read objects with other type is allowed according to strict aliasing rule.
#include <stdio.h>
#include <unistd.h>
void printOne(unsigned char v) {
const char* chars = "0123456789ABCDEF";
char data[2];
data[0] = chars[(v >> 4) & 0xf];
data[1] = chars[v & 0xf];
write(1, data, 2);
}
int main(void) {
int a;
int* p = &a;
/* to make sure the value is correct */
printf("p = %p\n", (void*)p);
fflush(stdout);
unsigned char ptrData[sizeof(int*)];
for(size_t i = 0; i < sizeof(int*); i++) {
ptrData[i] = ((unsigned char*)&p)[i];
}
/* print in reversed order, assuming little endian */
for (size_t i = sizeof(int*); i > 0; i--) {
printOne(ptrData[i - 1]);
}
return 0;
}
Or read data in a pointer variable as unsigned char array without copying:
#include <stdio.h>
#include <unistd.h>
void printOne(unsigned char v) {
const char* chars = "0123456789ABCDEF";
char data[2];
data[0] = chars[(v >> 4) & 0xf];
data[1] = chars[v & 0xf];
write(1, data, 2);
}
int main(void) {
int a;
int* p = &a;
/* to make sure the value is correct */
printf("p = %p\n", (void*)p);
fflush(stdout);
/* print in reversed order, assuming little endian */
for (size_t i = sizeof(int*); i > 0; i--) {
printOne(((unsigned char*)&p)[i - 1]);
}
return 0;
}
It would be easy to use printf %p but I am only allowed to use write from unistd.
Then form a string and print that.
int n = snprintf(NULL, 0, "%p", (void *) p);
char buf[n+1];
snprintf(buf, sizeof buf, "%p", (void *) p);
write(1, buf, n);
Using a pointer converted to an integer marginally reduces portability and does not certainly form the best textual representation of the pointer - something implementation dependent.
With uintptr_t it works but with an unsigned integer it only prints half of the address.
unsigned is not specified to be wide enough to contain all the information in a pointer.
uintptr_t, when available (very common), can preserve most of that information for void pointers. Good enough to round-trip to an equivalent pointer, even if in another form.

Convert integer to byte array produces unexepected results

OK...this seems like a fairly easy problem but I can't figure out what is going on here. I have the following code to convert an integer to a byte array and test the output:
#include <stdio.h>
void int2bytearray(char *byte_array, int size, int num)
{
for (int i = 0; i < size; i++)
{
byte_array[i] = (num >> 8*i) & 0xFF;
}
}
int main()
{
int test_int = 657850;
int size = sizeof(int);
printf("Size is %d\n", size);
printf("Size of char is %d\n", (int)sizeof(char));
char test_array[size];
printf("Size of first entry %d\n", (int)sizeof(test_array[0]));
int2bytearray(test_array, size, test_int);
for (int i=0; i < size; i++)
{
printf("%#02x", test_array[i]);
}
printf("\nFirst byte is %#.2X", test_array[0]);
return 0;
}
I expect main to return an array of bytes, but the first "byte" appears to be a 32 bit integer.
Unfortunately, I get the following output:
Size is 4
Size of char is 1
Size of first entry 1
0xffffffba0x90xa00
First byte is 0XFFFFFFBA
Can someone tell me why this first byte is printing out as 0XFFFFFFBA? Why is it a 32-bit integer and not a byte as defined?
The problem is related both to the type being used and how you're printing the values.
The first element in the array has value 0xBA which as a signed char is -70 in decimal. When this value is passed to printf it is converted to type int, so now you have a 32 bit value of -70 whose representation is 0XFFFFFFBA you then print it using %X it which prints an unsigned int in hex.
There are two ways to fix this.
First, change the type of test_array to unsigned char. Then the values stored will be positive and print correctly. The other option is to use %hhX as the format specifier which states to print the value as an unsigned char which will print the proper number of digits.

Putting Hex into a byte array

I am trying to put hex values into a Byte[], Trying to achieve 78,66,1E,B5,4F,E7,67,63
#define BYTE unsigned char
int num = 1;
long long hex[]
{
0x78661EB54FE76763,
};
int main()
{
for (int c = 0; c < num; c++)
{
printf("%llx\n", hex[c]);
unsigned int number = hex[c];
unsigned int ef = number & 0xff;
unsigned int cd = (number >> 8) & 0xff;
unsigned int ab = (number >> 16) & 0xff;
printf("%x", number & 0xff);
BYTE data2[8]{
ef, cd, ab
};
}
}
Update:
Basically I have an array of 30 odd hex values. I am trying to loop through that array called hex[], then for each hex value separate it into 2's ie 78,66,1E,B5,4F,E7,67,63 then add each one into an array of type BYTE which will hold the hex value in 8 pairs so data[0] will have the value of 78 up to data[8] which will have the value of 63, So I can then pass the array of type BYTE to another method for further work
Here is the solution that you want:
#include <stdio.h>
typedef unsigned char BYTE;
int main()
{
int i,j;
long long hex=0x78661EB54FE76763;
BYTE val[8];
for(j=0,i=7; i>=0; i--,j++){
val[j]= (hex>>(i*8))&0xff;
}
printf("Hexadecimal bytes are:\n");
for(j=0;j<8;j++){
printf("%02X ",val[j]);
}
return 0;
}
And the output is:
Hexadecimal bytes are:
78 66 1E B5 4F E7 67 63
Assuming that BYTE is a type
BYTE data2[] = {ef, cd, ab, '\0'};
Use the null terminator to allow printing with "%s" and printf().
Of course, you can add the rest of the bytes.
This is a pretty simple task to accomplish all you need is the initialization values that you have given. long long hex[] = { 0x78661EB54FE76763 };
Next, you need a char pointer that is pointing to the hex array
unsigned char* pByte = (unsigned char*)hex; // Point to the first element in hex array
Then create an 8 byte buffer and clear it with memset:
unsigned char byteArray[8];
memset(byteArray, 0, sizeof(byteArray));
All you need to do now is dereference your char pointer and place the value into your 8 byte buffer.
// Loop through the hex array and assign the current byte
// the byte pointer is pointing to then increment the byte pointer
// to look at the next value.
// This for loop is for a system that is little endian (i.e. win32)
for (int i = 7; i >= 0; i--)
{
byteArray[i] = *pByte;
pByte++;
}
Note: Since I ran this with Visual Studio 2015 everything is little endian. This is why the first for loop is written the way it is.
See below for the full program listing I wrote & tested below demonstrating this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
long long hex[] = { 0x78661EB54FE76763 }; // Value of an element
unsigned char* pByte = (unsigned char*)hex; // Assign a char pointer to point to the first element in hex array
unsigned char byteArray[8]; // This is the byte buffer that will be populated from the hex array
memset(byteArray, 0, sizeof(byteArray)); // Clear out the memory of byte array before filling in the indices
// Loop through the hex array and assign the current byte
// the byte pointer is pointing to then increment the byte pointer
// to look at the next value.
// This for loop is for a system that is little endian (i.e. win32)
for (int i = 7; i >= 0; i--)
{
byteArray[i] = *pByte; // Dereference the pointer and assign value to buffer
pByte++; // Point to the next byte
}
// Print the byte array
for(int i = 0; i < 8; i++)
{
printf("The value of element %i is: %X\n", i, byteArray[i]);
}
printf("Press any key to continue..."); // Hold the console window open
getchar();
return 0;
}

Divide contents of a unsigned char array into 2 halves

I am wondering if anyone can help me I am only learning c, I am trying to Divide contents of a unsigned char array into 2 halves, which the result can stored in two unsigned int's,
For example purposes, I have some code below which adds a hex value into a BYTE array, so How would split the contents of val[] into two but keep the same order
#include <stdio.h>
typedef unsigned char BYTE;
int main()
{
// Sample purposes putting hex into val[8]
int i,j;
long long hex=0x78661EB54FE76763;
BYTE val[8];
for(j=0,i=7; i>=0; i--,j++){
val[j]= (hex>>(i*8))&0xff;
}
// How to split the contents of val[8] which now holds the hex
return 0;
}
I am trying to split the hex value into 78661EB5, 4FE76763 and store each one inside an unsigned int which is stored inside val[8] in my example
Your variable long long hex is not a "char array", but you can try something like this, notice unsigned types throughout.
#include <stdio.h>
#include <stdint.h>
int main(void)
{
uint64_t hex = 0x78661EB54FE76763;
uint32_t lo, hi;
hi = hex >> 32;
lo = hex & 0xFFFFFFFF;
printf("%08X %08X\n", hi, lo);
return 0;
}
Program output:
78661EB5 4FE76763
Create a helper function that takes a pointer to an array of unsigned char and call it twice.
Left some things out for OP to discover.
unsigned long form_big_endian4(const unsigned char * x) {
unsigned long y = TBB; // What should the initial value be?
for (int i = 0; i < TBD; i++) { // How many times to loop?
y *= TBD; // Hint: max value of 8 bits + 1
y += x[i];
}
return y;
}
#include <stdio.h>
int main(void) {
const unsigned char val[8] =
{ 0x78, 0x66, 0x1E, 0xB5, 0x4F, 0xE7, 0x67, 0x63 };
unsigned long half = form_big_endian4(val); // Why long: Hint how small can unsigned be?
printf("%08lX\n", half); // Why 0 in format? Why `lX`?
half = form_big_endian4(val + TBD); // How far an offset?
printf("%08lX\n", half);
return 0;
}

How to convert a string to binary?

I'm working on a C project and I have some instructions of type:
add $1 $2 $3
So I'm reading the line as a string, parsing through it and have a corresponding integer for add, say - 2. Could anyone please tell me how I could convert this to binary in order to write it to a file?
The registers are 5 bits and the operation is 6 bits. The total will be 32 (the last 10 bits are unused).
So the registers are stored in say op[] = "2", char r1[] = "1", char r2[] = "2" etc (note that register number can be as high as 31). Could anyone give me an example for a function that would convert this to binary in the format 000010 00001 00010 00011 0000000000
The easiest way will be using a bit field:
struct code {
unsigned opcode : 6;
unisgned operand1 : 5;
unisgned operand2 : 5;
unisgned operand2 : 5;
} test_code;
Now you can simply assign to the different members:
test_code.opcode = 0x02;
test_code.operator1 = 0x01;
test_code.operator2 = 0x02;
test_code.operator3 = 0x03;
atoi(op) will give you 2, so you can just string it together
As far as putting it into that structure you want, just create a structure that has bitfields in it and place it in a union with a 32 bit unsigned integer, and you can take the value directly.
Quick pseudo code
const char* int32_to_bin(int32_t value) {
int pos = 0;
char output[33];
while(value > 0) {
if (value & 1) output[pos++] = '1';
else output[pos++] = '0';
value >>= 1;
}
output[pos] = 0;
return output;
}
What you're asking is a C question but you tag as objective-c so I'll cover both.
C:
These variables such as op[].. are really defined as like char op[..] (not sure if your length), which are C strings of course.
So the operation is 6 bit and each register is 5 bits, that's 15 + 6 = 21 bit word. I'll assume the top 11 bits are zeroes.
What you need are 4 more variables that are integers:
int opint; int r0int; int r1int; int r2int;
You want the integer value of those strings to go in to those integers. You can use atoi() to achieve this, such as opint = atoi(op);
Now that you've got your integers derived from strings, you need to create the 32 bit word. The easiest way to do this is to first create one integer that holds those bits in the right place. You can do it (assuming 32 bit integers) like this:
int word = 0;
word |= ((opint & 0x3f) << (21 - 6))) |
(r0int & 0x1f) << (21 - 11)) |
(r1int & 0x1f) << (21 - 16))
(r2int & 0x1f));
Where the << is shifting in to place. After this, you should have the word integer properly formed. Next, just turn it in to a binary representation (if that's even necessary? Not sure on your application)
Objective-C
The only difference is that I assume those strings start as NSString *op; etc. In this case, get the integers by opint = [op intValue];, then form the word as I describe.
This code will convert a string to binary
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* stringToBinary(char* s) ;
void binchar(char output[], char character);
void itoa(int value, char* str, int base);
int main(int argc, char const *argv[])
{
printf("%s\n", stringToBinary("asdf") );
}
char* stringToBinary(char* s) {
if(s == NULL) return 0; /* no input string */
size_t len = strlen(s);
char *binary = malloc(len*8 + 1); // each char is one byte (8 bits) and + 1 at the end for null terminator
int i =0;
char output[9];
for(i=0; i< len; i++){
binchar(output, s[i]);
strcat(binary,output);
}
return binary;
}
void binchar(char output[], char character)
{
//char output[9];
itoa(character, output, 2);
}
// since GCC is not fully supporting itoa function here is its implementaion
// itoa implementation is copied from here http://www.strudel.org.uk/itoa/
void itoa(int value, char* str, int base) {
static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz";
char* wstr=str;
int sign;
// Validate base
if (base<2 || base>35){ *wstr='\0'; return; }
// Take care of sign
if ((sign=value) < 0) value = -value;
// Conversion. Number is reversed.
do *wstr++ = num[value%base]; while(value/=base);
if(sign<0) *wstr++='-';
*wstr='\0';
// Reverse string
void strreverse(char* begin, char* end);
strreverse(str,wstr-1);
}
void strreverse(char* begin, char* end) {
char aux;
while(end>begin)
aux=*end, *end--=*begin, *begin++=aux;
}

Resources