How to read 3 bytes as a whole number? - c

How do I read 3 bytes from unsigned char buffer at once (as a whole number)?
uint_24 p = *(unsigned char[3])buffer;
The above code doesn't work.

If the buffer can be redefined as part of a union and integer endian is as expected:
union {
unsigned char buffer[3];
uint_24 p;
} x;
foo(x.buffer); // somehow data is loaded into x.buffer
uint_24 destination = x.p; // read: let compiler do the work
By putting into a union, alignment issues are satisfied.

The short answer is: you can't (unless the machine int size is 3 bytes).
As machines generally have an even number of bytes as its int size (word size, register size), the hardware architecture will always fetch an even number of bytes from memory over the bus into its registers, or can fetch one single byte into a (lower) register. Hence the solutions provided in the comments to your question load a byte, shift it left and load the next byte etc. Alternatively you can fetch a word and AND-out the upper byte(s). You must also take the endianness into account. Lastly, not all machines can read ints starting at odd memory addersses, or they require them to be alligned at some even multiple.

you can copy any number of bytes that you want as following:
#include <stdio.h>
void showbits(int n)
{
int i,k,andmask;
for(i=31;i>=0;i--)
{
andmask = 1 << i;
k = n & andmask;
k == 0 ? printf("0") : printf("1");
}
printf("\n");
}
int main()
{
unsigned char buff[] = {'a',0,0,
0,'b',0,
0,0,'c'};
//'a'=97=01100001
//'b'=98=01100010
//'c'=99=01100011
void * src_ptr= (void *) buff;
int i;
for(i = 0 ; i < sizeof(buff) ; i += 3)
{
int num = 0 ;
void * num_ptr = &num;
memcpy(num_ptr , src_ptr , 3);
showbits(num);
src_ptr += 3;
}
return 0;
}
output:
00000000000000000000000001100001 00000000000000000110001000000000
00000000011000110000000000000000

Related

Memory leak using Malloc/Free in C

I've been reading up on the use of pointers, and allocating memory for embedded projects. I must admit, that i perhaps don't understand it fully, as i can't seem to figure where my problem lies.
My two functions are supposed to take 4 float values, and return 16 bytes, that represent these, in order to transfer them through SPI. It works great, but only for a minute, before the program crashes and my SPI and I2C dies, lol.
Here are the functions:
/*Function that wraps a float value, by allocating memory and casting pointers.
Returns 4 bytes that represents input float value f.*/
typedef char byte;
byte* floatToByteArray(float f)
{
byte* ret = malloc(4 * sizeof(byte));
unsigned int asInt = *((int*)&f);
int i;
for (i = 0; i < 4; i++) {
ret[i] = (asInt >> 8 * i) & 0xFF;
}
return ret;
memset(ret, 0, 4 * sizeof(byte)); //Clear allocated memory, to avoid taking all memory
free(ret);
}
/*Takes a list of 4 quaternions, and wraps every quaternion in 4 bytes.
Returns a 16 element byte list for SPI transfer, that effectively contains the 4 quaternions*/
void wrap_quaternions(float Quaternion[4], int8_t *buff)
{
uint8_t m;
uint8_t n;
uint8_t k = 0;
for (m = 0; m < 4; m++)
{
for (n = 0; n < 4; n++)
{
byte* asBytes = floatToByteArray(Quaternion[m]);
buff[n+4*k] = asBytes[n];
}
k++;
}
}
The error message i receive after is the following, in the disassembly window of Atmel Studio
Atmel studio screenshot
You might drop all the dynamic memory allocation completely.
void floatToByteArray(float f, byte buf[4])
{
memcpy(buf, &f, sizeof(f));
}
void wrap_quaternions(float Quaternion[4], int8_t *buff)
{
for (int i = 0; i < 4; i++)
{
floatToByteArray(Quaternion[i], &buf[4*i]);
}
}
With this approach you do not need to care about freeing allocated memory after use. It is also much more efficient because dynamic memory allocation is rather expensive.
Gerhardh is correct, return prevent the memory from being released.
If you need to return 4 bytes, you might check if your environment can return a uint32_t or something like that.
As already mentioned, the lines below return ret; are never executed. And anyway if you want to return allocated memory in a function (what is fine) you can't free it in the function itself but it has to be freed by the caller when it isn't needed anymore. So your calling function should look like
/*Takes a list of 4 quaternions, and wraps every quaternion in 4 bytes.
Returns a 16 element byte list for SPI transfer, that effectively contains the 4 quaternions*/
void wrap_quaternions(float Quaternion[4], int8_t *buff)
{
uint8_t m;
uint8_t n;
uint8_t k = 0;
for (m = 0; m < 4; m++)
{
byte* asBytes = floatToByteArray(Quaternion[m]); // no need it to call for every n
for (n = 0; n < 4; n++)
{
buff[n+4*k] = asBytes[n];
}
free(asBytes); // asBytes is no longer needed and can be free()d
k++;
}
}
regarding:
buff[n+4*k] = asBytes[n];
This results in:
buff[0] << asBytes[0] // from first call to `byte* floatToByteArray(float f)`
buff[4] << asBytes[1] // from second call to `byte* floatToByteArray(float f)`
buff[8] << asBytes[2] // from third call to `byte* floatToByteArray(float f)`
buff[12] << asBytes[3] // from forth call to `byte* floatToByteArray(float f)`
most of the above problem can be fixed by using memcpy() to copy the 4 bytes from asBytes[] to buff[] similar to:
memcpy( &buff[ n*4 ], asBytes, 4 );
Of course, there is also the consideration: Is the length of a float, on your hardware/compiler actually 4 bytes.
'magic' numbers are numbers with no basis. 'magic' numbers make the code much more difficult to understand, debug, etc. I.E. 4. Suggest using something like: length = sizeof( float ); then using length everywhere that 4 is currently being used, except for the number of entries in the Quaternion[] array. for that 'magic' number, strongly suggest the statement: #define arraySize 4 be early in your code. Then using arraySize each time the code references the number of elements in the array

Convert serial port data to float in C with union

I'm using a C program on Linux to read data from a serial port.
The data to read comes from Code Composer Studio from the line: UART_writePolling(uartHandle, (uint8_t*) &value, sizeof(float));
value is the float I want to read in C, where value = 1.5.
When I read in the data from the serial port, in C, into a buffer and print with printf("%u\n", (int)buffer[i]);
I get value to be:
0
0
4294967232
63
and when I insert buffer[i] into a.array and print with
printf("%d\n", a.array[i]);
I get value to be:
0
0
-64
63
I've also tried using unions:
unsigned int value = 0;
for (int j = 3; j >= 0; j--){
//value <<= 8;
value = value + (int)a.array[i+8+j];
}
printf("value: %u\n", value);
data.u = value;
printf("(float): %f\n", data.f);
which doesn't give the correct answer.
How can I use union to get the correct data as a float?
Do I need to use <<?
EDIT: better idea of the code
//headers
typedef struct {
int *array;
size_t used;
size_t size;
} Array;
void initArray(Array *a, size_t initialSize) {
a->array = (int *)malloc(initialSize * sizeof(int));
a->used = 0;
a->size = initialSize;
}
... //more functions/code to resize array and free the memory later
union Data {
float f;
unsigned int u;
};
int main(){
union Data data;
//open serial port code
char buffer[1]; /* Buffer to store the data received,
reading one at a time */
Array a;
initArray(&a, 5); /* initialise an array to store the read data
that is read into buffer*/
//while loop to read in data for some amount of time/data
int b_read = 0;
b_read = read(fd, &buffer, sizeof(buffer));
for (int i=0; i<b_read; i++){
printf("%u\n", (int)buffer[i]);
// how the first set of values above were printed
insertArray(&a, buffer[i]);
// also adding the values read to buffer into array a
}
//end while
// close the port
for(int i=0; i<no. of elements in array a; i++){
printf("%d\n", a.array[i]);
// how the second set of results were printed
}
//below is an attempt at using union and <<:
unsigned int value = 0;
for (int j = 3; j >= 0; j--){
//value <<= 8;
value = value + (int)a.array[i+8+j]; //index used is particular to my code, where value is in a specific place in the array
}
printf("value: %u\n", value);
data.u = value;
printf("(float): %f\n", data.f);
//these printfs don't give a reasonable answer
// free memory
return 0;
}
Once the bytes are in buffer starting at offset i, you can reinterpret the bytes as a float with:
float f;
memcpy(&f, buffer+i, sizeof f);
To use a union, you could use:
union { uint32_t u; float f; } x;
x.u = value;
float f = x.f;
However, this requires that value contain all 32 bits that represent the float. When you attempted to construct the value with:
//value <<= 8;
value = value + (int)a.array[i+8+j];
There are two issues. First, value <<= 8 is needed. I presume you tried it first and did not get a correct answer, so you commented it out. However, it is required. Second, this code to insert the bytes one-by-one into value is order-dependent. Once the shift is restored, it will insert greater-addressed bytes into less-significant bits of value. Systems generally arrange bytes in objects in one of two orders: More significant bytes in lower addresses or more significant bytes in greater addresses. We do not know which order your system uses, so we do not know whether your code to insert the greater-addressed bytes in less significant bytes is correct.
Note: The above assumes that the bytes are read and written in the same order, or that issues of endianness have already been handled in other code.
You use printf with %u but cast into a int. So maybe it's not surprising to have this behavior since 2^32 = 4294967296, and 4294967296 - 64 (your second printf result) = 4294967232 (your first printf result).
Just cast into "unsigned" if you use "%u" or cast into "int" if you use "%d".

issue convert double range number to binary

I have a problem to convert integer type's double rage number to binary as the below,
void intToBin(int digit) {
int b;
int k = 0;
char *bits;
int i;
bits= (char *) malloc(sizeof(char));
while (digit) {
b = digit % 2;
digit = digit / 2;
bits[k] = b;
k++;
}
for ( i = k - 1; i >= 0; i--) {
printf("%d", bits[i]);
}
}
But as you can see the that function's arguments input is integer.
I came across the error when I tried with intToBin(10329216702565230)
because 10329216702565230 is over integer range.
How can I extend what that have integer type's double rage number to binary ?
update
I've updated the below code
void intToBin(uint64_t digit) {
int b;
int k = 0;
char *bits;
int i;
bits = malloc(sizeof digit * 64);
while (digit) {
b = digit % 2;
digit = digit / 2;
bits[k] = b;
k++;
}
for ( i = k - 1; i >= 0; i--) {
printf("%d", bits[i]);
}
}
But I didn't get it what should I do to get the 2's complement ?
m
dmnngn
Solution is to use type which supports that range of numbers.
Use unsigned long long or uint64_t(assuming you are passing non negative integers, otherwise use long long or int64_t). Then you call the function like this Edited to add int64_t to uint64_t from the comment posted. unsigned long long is 64 bits atleast - can even be wider. With OP's comment of getting 64 bits output - better to use (u)int64_t
intToBin(10329216702565230U)
In case you want to use negative numbers use long long.Call it like this
intToBin(10329216702565230L).
You didn't allocate enough memory - you were accessing memory that you haven't allocated, resulting in Undefined behavior. You have allocated 1 char first and then you didn't allocate. You can solve this by reallocating - reallocate memory inside the loop (reallocate 1 char at a time inside loop). And then use it. Instead of calling realloc multiple times why don't you allocate memory for 64 chars and then use it to store the result. And in the end, the left over space can be freed with another realloc call.
You don't need to cast the return value of malloc (void* to char* conversion is done implicitly).
You didn't check the return value of malloc. malloc may return NULL and in that case you have to handle that separately. For example:-
#define NBITS 64
...
...
bits = malloc(NBITS);
if( bits == NULL ){
perror("malloc failed");
exit(EXIT_FAILURE);
}
Note: The 64 magic number is coming introduced with the thought that unsigned long long is 64 bits atleast. So while converting we will be using that in case the number of bits exceeds 64 we will reallocate. A better choice is to use what chux said - sizeof digit * CHAR_BIT.
Also
bits[k] = b+'0';
We are putting the ascii value and then you can print it like this
printf("%c", bits[i]);
You forgot to free the allocated memory. Without freeing it (free(bits)), you have memory leak.
Davic C. Rankins comment
void intToBin(int digit)
{
int b;
int k = 0;
char *bits;
int i;
bits= (char *) malloc(sizeof(char));
while (digit) {
b = digit % 2;
digit = digit / 2;
bits[k] = b;
k++;
}
for ( i = k - 1; i >= 0; i--) {
printf("%d", bits[i]);
}
}
The answer is simple,
Replace int with int64_t to use 64 bits instead of 32.
Please try it and let us know
Replace int with int64_t to use 64 bits instead of 32.

Adding Zero padding to an array

I am doing a GHASH for the AES-GCM implementation.
and i need to implement this
where v is the bit length of the final block of A, u is the bit length of the final block of C, and || denotes concatenation of bit strings.
How can I do the concatenation of A block to fill in the zeros padding from v to 128 bit, as I do not know the length of the whole block of A.
So I just take the A block and XOR it with an array of 128 bits
void GHASH(uint8_t H[16], uint8_t len_A, uint8_t A_i[len_A], uint8_t len_C,
uint8_t C_i[len_C], uint8_t X_i[16]) {
uint8_t m;
uint8_t n;
uint8_t i;
uint8_t j;
uint8_t zeros[16] = {0};
if (i == m + n) {
for(j=16; j>=0; j--){
C_i[j] = C_i[j] ^ zeros[j]; //XOR with zero array to fill in 0 of length 128-u
tmp[j] = X_i[j] ^ C_i[j]; // X[m+n+1] XOR C[i] left shift by (128bit-u) and store into tmp
gmul(tmp, H, X_i); //Do Multiplication of tmp to H and store into X
}
}
I am pretty sure that I am not correct. But I have no idea how to do it.
It seems to me that you've got several issues here, and conflating them is a big part of the problem. It'll be much easier when you separate them.
First: passing in a parameter of the form uint8_t len_A, uint8_t A_i[len_A] is not proper syntax and won't give you what you want. You're actually getting uint8_t len_A, uint8_t * A_i, and the length of A_i is determined by how it was declared on the level above, not how you tried to pass it in. (Note that uint8_t * A and uint8_t A[] are functionally identical here; the difference is mostly syntactic sugar for the programmer.)
On the level above, since I don't know if it was declared by malloc() or on the stack, I'm not going to get fancy with memory management issues. I'm going to use local storage for my suggestion.
Unit clarity: You've got a bad case going on here: bit vs. byte vs. block length. Without knowing the core algorithm, it appears to me that the undeclared m & n are block lengths of A & C; i.e., A is m blocks long, and C is n blocks long, and in both cases the last block is not required to be full length. You're passing in len_A & len_C without telling us (or using them in code so we can see) whether they're the bit length u/v, the byte length of A_i/C_i, or the total length of A/C, in bits or bytes or blocks. Based on the (incorrect) declaration, I'm assuming they're the length of A_i/C_i in bytes, but it's not obvious... nor is it the obvious thing to pass. By the name, I would have guessed it to be the length of A/C in bits. Hint: if your units are in the names, it becomes obvious when you try to add bitLenA to byteLenB.
Iteration control: You appear to be passing in 16-byte blocks for the i'th iteration, but not passing in i. Either pass in i, or pass in the full A & C instead of A_i & C_i. You're also using m & n without setting them or passing them in; the same issue applied. I'll just pretend they're all correct at the moment of use and let you fix that.
Finally, I don't understand the summation notation for the i=m+n+1 case, in particular how len(A) & len(C) are treated, but you're not asking about that case so I'll ignore it.
Given all that, let's look at your function:
void GHASH(uint8_t H[], uint8_t len_A, uint8_t A_i[], uint8_t len_C, uint8_t C_i[], uint8_t X_i[]) {
uint8_t tmpAC[16] = {0};
uint8_t tmp[16];
uint8_t * pAC = tmpAC;
if (i == 0) { // Initialization case
for (j=0; j<len_A; ++j) {
X_i[j] = 0;
}
return;
} else if (i < m) { // Use the input memory for A
pAC = A_i;
} else if (i == m) { // Use temp memory init'ed to 0; copy in A as far as it goes
for (j=0; j<len_A; ++j) {
pAC[j] = A_i[j];
}
} else if (i < m+n) { // Use the input memory for C
pAC = C_i;
} else if (i == m+n) { // Use temp memory init'ed to 0; copy in C as far as it goes
for (j=0; j<len_A; ++j) {
pAC[j] = C_i[j];
}
} else if (i == m+n+1) { // Do something unclear to me. Maybe this?
// Use temp memory init'ed to 0; copy in len(A) & len(C)
pAC[0] = len_A; // in blocks? bits? bytes?
pAC[1] = len_C; // in blocks? bits? bytes?
}
for(j=16; j>=0; j--){
tmp[j] = X_i[j] ^ pAC[j]; // X[m+n+1] XOR A or C[i] and store into tmp
gmul(tmp, H, X_i); //Do Multiplication of tmp to H and store into X
}
}
We only copy memory in the last block of A or C, and use local memory for the copy. Most blocks are handled with a single pointer copy to point to the correct bit of input memory.
if you don't care about every little bit of efficiency (i assume this is to experiment, and not for real use?) just reallocate and pad (in practice, you could round up and calloc when you first declare these):
size_t round16(size_t n) {
// if n isn't a multiple of 16, round up to next multiple
if (n % 16) return 16 * (1 + n / 16);
return n;
}
size_t realloc16(uint8_t **data, size_t len) {
// if len isn't a multiple of 16, extend with 0s to next multiple
size_t n = round16(len);
*data = realloc(*data, n);
for (size_t i = len; i < n; ++i) (*data)[i] = 0;
return n;
}
void xor16(uint8_t *result, uint8_t *a, uint8_t *b) {
// 16 byte xor
for (size_t i = 0; i < 16; ++i) result[i] = a[i] ^ b[i];
}
void xorandmult(uint8_t *x, uint8_t *data, size_t n, unint8_t *h) {
// run along the length of the (extended) data, xoring and mutliplying
uint8_t tmp[16];
for (size_t i = 0; i < n / 16; ++i) {
xor16(tmp, x, data+i*16);
multgcm(x, h, tmp);
}
}
void ghash(uint8_t *x, uint8_t **a, size_t len_a, uint8_t **c, size_t len_c, uint8_t *h) {
size_t m = realloc16(a, len_a);
xorandmult(x, *a, m, h);
size_t n = realloc16(c, len_c);
xorandmult(x, *c, n, h);
// then handle lengths
}
uint8_t x[16] = {0};
ghash(x, &a, len_a, &c, len_c, h);
disclaimer - no expert, just skimmed the spec. code uncompiled, unchecked, and not intended for "real" use. also, the spec supports arbitrary (bit) lengths, but i assume you're working in bytes.
also, i am still not sure i am answering the right question.

Cast int to char array in C

Is is possible to convert int to "string" in C just using casting? Without any functions like atoi() or sprintf()?
What I want would be like this:
int main(int argc, char *argv[]) {
int i = 500;
char c[4];
c = (char)i;
i = 0;
i = (int)c;
}
The reason is that I need to generate two random ints (0 to 500) and send both as one string in a message queue to another process. The other process receives the message and do the LCM.
I know how to do with atoi() and itoa(). But my teachers wants just using cast.
Also, why isn't the following possible to compile?
typedef struct
{
int x;
int y;
} int_t;
typedef struct
{
char x[sizeof(int)];
char y[sizeof(int)];
} char_t;
int main(int argc, char *argv[])
{
int_t rand_int;
char_t rand_char;
rand_int.x = (rand() % 501);
rand_int.y = (rand() % 501);
rand_char = (char_t)rand_int;
}
Of course it's not possible, because an array is an object and needs storage. Casts result in values, not objects. Some would say the whole point/power of C is that you have control over the storage and lifetime of objects.
The proper way to generate a string containing a decimal representation of an integer is to create storage for it yourself and use snprintf:
char buf[sizeof(int)*3+2];
snprintf(buf, sizeof buf, "%d", n);
You have to convert 500 to "500".
"500" is the same as '5' then '0' then '0' then 0. The last element 0 is the null terminator of a string.
500 is equal to 5 * 100 + 0 * 10 + 0 * 1. You have to do some math here. Basically you have to use the / operator.
Then this could be also useful: '5' is the same as '0' + 5.
Without giving away an exact coded answer, what you'll want to do is loop through each digit of the integer (by computing its remainder modulo 10 via the % operator), and then add its value to the ASCII value of '0', casting the result back to a char, and placing that result in a null-terminated string.
An example which pretends like implicit casts don't exist might look like this:
char c = (char) ( ((int) '0') + 5 ); // c should now be '5'.
You can determine the length of the resulting string by computing the log base 10 of the number, or by simply allocating it dynamically as you go using realloc().
Casting is a horrible way to do this due to endianness, but here is an example anyhow - there are some occasions where it is useful (unions work better these days though, due to compiler handling of these types of casts).
#include <stdio.h> //for printf
#define INT(x) ((int*)(x)) //these are not endian-safe methods
#define CHAR(x) ((char*)(x))
int main(void)
{
int *x=INT(&"HI !");
printf("%X\n",*x); //look up the ascii and note the order
printf("%s\n",CHAR(x));
return 0;
}
For an int with a value <500, if the most significant byte comes first, then you get a "string" (pointer to a char array) of "" (or {0}) but if the endianness is LSB first (x86 is little endian) then you would get a usable 3 byte "string" char* (not necessarily human readable characters) but there is no guarantee that there will be a zero byte in an integer and since all you have is a pointer to the address where the int was stored, if you were to run normal string functions on it, they would go past the end of the original int into no-mans-land (in small test programs it will often be environment variables) ... anyhow for more portability you can use network byte order (which for little endian is a no-op):
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
These functions just byteswap as necessary to get network byte order. On your x86 they will be optimized away, so you might as well use them for portability.
Just because it is not listed yet: Here a way to convert int to char array with variable size allocation by using snprintf:
int value = 5
// this will just output the length which is to expect
int length = snprintf( NULL, 0, "%d", value );
char* valueAsString = malloc( length + 1 );// one more for 0-terminator
snprintf( valueAsString, length + 1, "%d", value );
get the number of divisions then add one by one to your buffer
char *int2str(int nb) {
int i = 0;
int div = 1;
int cmp = nb;
char *nbr = malloc(sizeof(char) * 12);
if (!nbr)
return (NULL);
if (nb < 0)
nbr[i++] = '-';
while ((cmp /= 10) != 0)
div = div * 10;
while (div > 0) {
nbr[i++] = abs(nb / div) + 48;
nb = nb % div;
div /= 10;
}
nbr[i] = '\0';
return (nbr);
}
Even more compact:
char *lotaa(long long nb) {
int size = (nb ? floor(log10(llabs(nb))) : 0) + (nb >= 0 ? 1 : 2);
char *str = malloc(size + 1);
str[0] = '-';
str[size] = 0;
for(nb = llabs(nb); nb > 0 || (size > 0 && str[1] == 0); nb /= 10)
str[--size] = '0' + nb % 10;
return (str);
}

Resources