Most efficient way to subtract arrays of unsigned chars in C - c

I'm using libpcap to analyze and process packets. I have to compare two arrays of unsigned chars, take the difference and save it to a hashtable. Another thread will periodically scans across the hashtable and compute for average,standard deviation, max and min.
My question is the following, what would be the most efficient way to perform subtraction on two arrays?
For example:
A="0x34 0x44 0x59 0x5B"
B="0x34 0x42 0x43 0x43"
My first thought is to convert it to an integer, by converting the array into an array of signed chars, doing take requires a function to perform lookup function. Because this is function is called for every packet received on the system.

use the union can make this simple, because different data types share the same memory, we can then use this feature to convert data type.
note the Little-endian
#include <stdio.h>
typedef union new_array{
struct array {
unsigned char f4;
unsigned char f3;
unsigned char f2;
unsigned char f1;
}array;
unsigned int int_array;
}new_array;
int main()
{
new_array A, B;
A.array.f1 = 0x34;
A.array.f2 = 0x44;
A.array.f3 = 0x59;
A.array.f4 = 0x5B;
B.array.f1 = 0x34;
B.array.f2 = 0x42;
B.array.f3 = 0x43;
B.array.f4 = 0x43;
printf("%u\n", A.int_array - B.int_array);
}

Related

Casting a float for int and int to float

Having a little difficulty with pointers. I have to store a float in an array of unsigned ints and be able to pull it out.
I know there is a special way to cast this so I don't reorder the bits, I think this is the correct way to store it when I want to put it into the array:
float f = 5.0;
int newF = (int *) f;
arrayOfInts[0] = *newF
Which seems to successfully store the value in the array.
However, at some point I have to pull the value back out of the array of ints, this is where my confusion comes in (assuming I inputed into the array correctly)
float * f = (float *) arrayOfInts[0]
int result = *f;
however, that gives me the warning: 'cast to pointer from integer of different size'
I can't really think of how to solve that without some sort of long cast.. which doesn't seem right..
I don't want to lose the value or damage the bits.. obviously It will lose decimal point precision.. but I know theirs some way to safety convert back and forth
I have to store a float in an array of unsigned ints and be able to pull it out.
Use a union and unsigned char[]. unsigned char is specified to not have any padding and all bit combinations are valid. This is not always true of many other number types. By overlaying the float with unsigned char[], code can examine each "byte" of the float, one at a time.
union {
float f;
unsigned char uc[sizeof (float)];
} x;
// example usage
x.f = 1.234f;
for (unsigned i = 0; i<sizeof x.uc; i++) {
printf("%u:%u\n", i, 1u*x.uc[i]);
}
Sample output: Yours may vary
0:182
1:243
2:157
3:63
float --> unsigned char[] --> float is always safe.
unsigned char[] --> float --> unsigned char[] is not always safe as a combination of unsigned char[] may not have a valid float value.
Avoid pointer tricks and casting. There are alignment and size issues.
// Poor code
float f = 5.0f;
int newF = *((int *) &f); // Conversion of `float*` to `int*` is not well specified.
Code can also overlay with fixed-width no-padding types like (u)int32_t if they exist (they usually do) and match in size.
#include <stdint.h>
union {
float f;
uint32_t u32;
} x32;
#include <assert.h>
#include <inttypes.h>
// example usage
assert(sizeof x32.f == sizeof x32.u32);
x32.f = 1.234f;
printf("%" PRNu32 "\n", x32.u32);
}
Example output: yours may vary
1067316150
To convert a float to an int
float fval = 123.4f;
int ival = *(int*)&fval;
To convert back
int ival = /* from float */
float fval = *(float*) &ival;
it won't work if float and int are different sizes, but presumably you know that already. The unsigned char union method outlined in other answer for chux is more robust, but over-complicated for what you probably want to do.

How do I store an unsigned short into a char array? C language

I'm a beginner in C language, I was wondering how I store an unsigned short into a char array?
unit16_t is unsigned short, and below is my code.
uint16_t combined = 1234;
char echoPrompt[] = {combined};
EDIT:
Sorry for being unclear
I need echoPrompt to be a char array and combined needs to be an integer. I am passing echPrompt as a char array to a UART_write which required a char array.
You cannot pass an array to a function. You can pass a pointer. Pointers are not arrays.
If your UART_write looks anything like any of the standard C/POSIX functions write, fwrite etc, you need
result = UART_write (...,
(char*)&combined,
sizeof(combined), ...);
There is no need in a char array.
if I understood correctly, you want to save each upper and lower 1 byte of short in char array.
well, why don't you just use union?
typedef struct uint16_s{
char upper;
char lower;
} uint16_s;
typedef union uint16_u{
uint16_s sBuf;
uint16_t tBuf;
} uint16_u;
uint16_u combined;
combined.tBuf = 1234;
char echoPrompt[] = {combined.sBuf.upper, combined.sBuf.lower};

C, Creating a 32 bit pointer to a 8 bit array

I have a buffer where each entry in the buffer is 8 bits in size:
uint8_t Buffer[10] = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
What I need to do is to create pointers to that array, for example 16 bit and 32 bit pointers. For example:
uint32_t *x;
x = Buffer;
uint32_t *y;
y = Buffer+4;
uint16_t *z;
z = Buffer+8;
Where each variable would then read from the array, for example:
x = 0x78563412
y = 0xf4f3f2f1
z = 0xf6f5
This works completely fine, the problem is that I'm getting warnings about incompatible pointer types. So I was wondering if there is an alternative way of doing this or if I'll just have to live with the warnings? Or am I simply doing this completely the wrong way?
Please note that this code will be executed on a single type of platform where the endianness is always the same and the size of data types is always the same.
You should heed the warnings; what you're doing is undefined behavior. Type aliasing like that is undefined behavior, particularly since there is no guarantee that Buffer has the correct alignment such that it can be accessed as an int/short. If Buffer has the correct alignment, then you can just explicitly cast and it's okay (and the warning will go away).
You have two options:
One, you align the buffer as the larger of the two types. Be careful that your pointer arithmetic doesn't throw off the alignment:
#include <stdalign.h>
alignas(int) unsigned char Buffer[10] = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
unsigned int *x;
x = (unsigned int*)(Buffer);
unsigned int *y;
y = (unsigned int*)(Buffer+4);
unsigned short *z;
z = (unsigned short*)(Buffer+8);
Two, you create an unsigned int/unsigned short variable and then memcpy the bytes you're interested in into the variable:
unsigned int x;
memcpy(&x, Buffer, 4);
unsigned int y;
memcpy(&y, Buffer + 4, 4);
unsigned short z;
memcpy(&z, Buffer + 8, 2);
The problem with your approach is that it assumes a particular endianness of underlying hardware. Different computers will interpret a sequence of hex bytes
01 23 45 67
as eiter
01234567 or 67452301
Your program may compile and run on both systems, but since the result is hardware-specific, the compiler must warn you of the possibility.
The proper way of forcing a particular endianness is by using an array of integers, convert them using hton and ntoh functions, and set individual bytes either directly by casting a pointer to unsigned char*, or with memcpy.
You might want to use a union
#include <stdint.h>
#include <stdio.h>
typedef union{
uint8_t Buffer[10];
struct{
uint32_t x;
uint32_t y;
uint16_t z;
};
}MYSTRUCT;
int main(){
MYSTRUCT b = {0x12,0x34,0x56,0x78,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6};
printf("x=%#x y=%#x z=%#x\n",b.x,b.y,b.z);
return 0;
}

Sizeof next byte in byte array

I have an unsigned char and I add integers to it but I want to get the sizeof next byte (i.e sizeof unsigned short int or unsigned int and so on).
The following code demonstrates what I want:
#include <stdio.h>
static void write_ushort(unsigned char *b, unsigned short int value) { b[1] = value >> 8; b[0] = value; }
static void write_ulong(unsigned char *b, unsigned long int value) { write_ushort(b + 2, value >> 16); write_ushort(b, value); }
static unsigned short int read_ushort(const unsigned char *b) { return b[1] << 8 | b[0]; }
static unsigned long int read_ulong(const unsigned char *b) { return read_ushort(b + 2) <<16 | read_ushort(b); }
int main() {
unsigned char b[2];
unsigned int v0; /* 4 */
unsigned short int v1; /* 2 */
v0 = 200; v1 = 1235;
write_ushort(&b[0], v0); write_ulong(&b[1], v1);
/* what i expect printf to output is:
* 4 2
* but it obviously outputs 1 1 */
printf("%d %d\n", read_ushort(&b[0]), read_ulong(&b[1]));
printf("%d %d\n", (int)sizeof(b[0]), (int)sizeof(b[1]));
return 0;
}
This isn't possible. The sizeof operator will return the size of a type, or the size of the declared type of a variable. You can't massage anything else out of it, and your code won't keep track of what type of variable a number was stored in before you assigned it to a new variable.
Regardless of the type of v0 or v1, when they're stored in elements of your array, they are converted to unsigned char.
If you want 4 2 as output, you'll need to pass sizeof(v0) and sizeof(v1) to printf, or keep track of this some other way.
C is statically typed, and you can't just change the data type of a variable (or array) by assigning something to it. In fact you can't change the data type of a variable at all: a variable corresponds (almost exactly) to a certain chunk of memory with its size defined at compile time. You can cast variables so that they are treated as though they were a different type for a specific operation, but the chunk of memory is the same size always.
And, since a variable is just a block of memory there is no way for the computer (or compiler) to know that you are using a char[2] array to store a short or a long. You have to keep track of this yourself.
Here is a major problem:
write_ulong(&b[1], v1);
You take the second byte (of a two-byte array) and pass it to write_ulong where it's handled as an array of four bytes. This means you are writing several bytes beyond the original array b and overwrite the stack. This is undefined behavior and will make your program behave very strange.

Reserve space C

Can you tell me the best way to reserve for example 1000 bits from memory in C?
I'm doing a program and i need to manage flags (values =0 or =1). What is the most efficient way to do that?
I was thinking in reserve the space needed and control the flags (bits) using masks.
Thank you
The least amount of memory you can access/address in C is a byte which is of CHAR_BIT bits width (which is guranteed to be at least 8 bits long). So, if you are looking for a packed structure you could use ceil(1000/8) bytes.
You may want to take a look at this SO question for bit manipulation details.
You can use the bool type:
#include <stdbool.h> // for bool
#include <stdlib.h> // for malloc
#define N 1000
bool *b = malloc(N * sizeof *b);
// for example to set the 42th element to 1
b[41] = 1;
something like?
struct bitf
{
unsigned char b:1;
};
struct bitf[1000];
if you won't to use bitmask the max size is the max size of a variable on your computer.
Error trying to define a 1,024-bit (128 Byte) Bit Field
or for min memory:
#include <stdio.h>
int main(void)
{
struct bitf
{
unsigned char a:1;
unsigned char b:1;
unsigned char c:1;
unsigned char d:1;
unsigned char e:1;
unsigned char f:1;
unsigned char g:1;
unsigned char h:1;
};
struct bitf number[125];
number[100].a = 1;
number[110].h =1;
printf("size: %d a:%d h:%d\n",sizeof(number), number[100].a ==0, number[110].h ==1);
return 0;
}
output:
size: 125 a:0 h:1

Resources