C - Sum of Array using pointers - c

I've tried many different variants of both of the ways, and cannot get it to sum the array. It's passed into the function as a pointer and need to calc the mean and return.
unsigned char calcMean(unsigned char *buffer, int height, int width)
{
unsigned char mean, sum=0;
counter i, k;
int size;
size = width*height;
mean = 0;
for (i = 0; i < size; i++) {
sum += buffer[i];
}
/*
for(k=0;k<(width*height);k++)
{
mean = mean + *Buffer;
frameBuffer++;
printf("%d\n", mean);
}
*/
return sum;
}

mean can be a char, since you would divide by size to calculate it. But the sum itself can be as high as size * 255 (8bits of unsigned char).
width * height can overflow too.
To be at the safe side (on 32 or 64bit machines), consider this:
16bit * 16bit integer would require a 32bit integer (for the dimension).
An unsigned char array with a size up to 4294967295 would then require 64bits for the sum.
So, if possible, use explicit integer sizes (C99):
uint8_t calcMean(uint8_t *buffer, uint16_t height, uint16_t width)
{
uint64_t sum=0;
size_t i;
size_t size;//size_t is large enough to store a pointer,
//so it would have 32 or 64bits on corresponding platforms
//(see uintptr_t, etc.)
size = ((size_t)width)*((size_t)height);
for (i = 0; i < size; i++) {
sum += buffer[i];
}
return sum / size;
}

To guard yourself from buffer overflow for the buffer[] array, assuming you have array defined and initialized with values, pass size of array along with pointer to array's first element rather than the method you have currently to calcMean().
Call to calcMean() shall be:
uint8_t array_name[3]={1,2,3}; /* Array size and values assumed */
...
calcMean(array_name, sizeof(array_name))
calcMean() definition shall be :
uint8_t calcMean(uint8_t *buffer, size_t buffer_size)
{
uint64_t sum=0;
size_t i;
for(i = 0; i < buffer_size; i++)
{
sum += buffer[i];
}
..../*Do whatever you want if at all needed */
return (sum / size);
}

Related

Copying unsigned char array to uint32_t, and vice versa

I'm trying to iteratively copy an unsigned char array to a uint_32t variable (in 4 byte blocks), perform some operation on the uint_32t variable, and copy it back to the unsigned char array.
Here's my code:
unsigned char byteArray[len]
for (int i=0; i<len; i+=4) {
uint32_t tmpInt = 0;
memcpy(&tmpInt, byteArray+(i*4), sizeof(uint32_t));
// do some operation on tmpInt here
memcpy((void*)(byteArray+(i*4)), &tmpInt, sizeof(uint32_t));
}
It doesn't work though. What's wrong, and how can I achieve what I want to do?
The problem is that you are adding 4 to i with each iteration and multiplying by 4. You should be using byteArray + i.
Also, as #WeatherVane pointed out below, your loop would be more consistent with a sizeof():
for (int i = 0; i < len; i += sizeof(uint32_t)).
As others pointed out you are doing too much by incrementing i as well as multiplying it by the size of your target.
On top of this
the code shown might run into a buffer overflow issue reading beyond the source array.
the sizeof operator evaluates to size_t not int.
the code repeats defining the size of the target independently several times.
Fixing all, the result might look like this:
unsigned char byte_array[len];
typedef uint32_t target_type;
const size_t s = sizeof (target_type);
for (size_t i = 0; i < (len/s)*s; i += s) {
target_type target;
memcpy(&target, byte_array + i, s);
// do some operation on target here
memcpy(byte_array + i, &target, s);
}
To avoid the typedef just define the target outside of the for-loop:
unsigned char byte_array[len];
{
uint32_t target;
const size_t s = sizeof target;
for (size_t i = 0; i < (len/s)*s; i += s) {
memcpy(&target, byte_array + i, s);
// do some operation on target here
memcpy(byte_array + i, &target, s);
}
}
An equivalent to
byte_array + i
would be
&byte_array[i]
which might be more intuitively to read.
To avoid the "strange" (len/s)*s one could step away from using an index at all, but use a pointer instead:
for (unsigned char p = byte_array; p < byte_array + len; p += s) {
memcpy(&target, p, s);
// do some operation on target here
memcpy(p, &target, s);
}
In my opinion this is a more elegant solution.

Calculate Checksum of a custom struct I've created

Hi guys I'm trying to calculate the checksum of a struct that I've made.
I created a struct packet that contains multiple char and int variables.
Is there a way to calculate the checksum of such a struct?
My first guess was, calculating the packet size and then use a cycle to calculate for each position its value, sum those together and then return that value.
The problem is that I don't know how to calculate each position of this packet, since there are multiple type of variable cause it's a struct.
Do you have any suggestion?
What you need here is to access each byte of the struct. You can do that by taking its address, casting it to unsigned char *, assigning the address to a variable of that type, then using the variable to loop through the bytes:
unsigned int sum = 0;
unsigned char *p = (unsigned char *)&mystruct;
for (int i=0; i<sizeof(mystruct); i++) {
sum += p[i];
}
Note however that if your struct contains any padding that the values of the padding bytes are unspecified, so that can mess with your checksum. If that's the case, then you'll need to do the above for each field in the struct individually.
For example:
unsigned int sum = 0;
unsigned char *p = (unsigned char *)&mystruct.field1;
for (int i=0; i<sizeof(mystruct.field1); i++) {
sum += p[i];
}
p = (unsigned char *)&mystruct.field2;
for (int i=0; i<sizeof(mystruct.field2); i++) {
sum += p[i];
}

C, memset a double array failed

I want to declare a double type array dynamically, so here is my code
void function(int length, ...)
{
...
double *a = malloc(sizeof(double) * length);
memset(a, 1, sizeof(double) * length);
for (int i = 0; i < length; i++)
{
printf("%f", a[i]);
}
...
}
When I pass a length of 2, the code does not print all 1s. It just prints the following:
7.7486e-304
7.7486e-304
So, what should I do to fix it?
memset sets bytes. You're trying to set doubles. Just loop from 0 to length and set each one to 1.0:
for (int i = 0; i < length; i ++)
{
a[i] = 1; // or 1.0 if you want to be explicit
}
You are confusing setting an array and setting the underlying memory that stores an array.
A double is made up of 8 bytes. You are setting each byte that makes up the double to 1.
If you want to initialise each element of the array to 1.0 then you can use a for(;;) loop or since you do seem to be using C++ you can use a container and use a constructor to initialise each element (if the constructor has the ability) or use an algorithm to achieve the same effect.
memset sets every byte of your array to 1 not every int or double element.
You are trying to set double values (maybe 8 or more bytes.) Your approach will only work for the number 0.0 as it happens to be represented with all bytes 0 on systems that use IEEE-754 floating point formats. Note that this would be non portable as the C Standard allows other representations for floating point values.
If a was pointing to an array of integers, your approach would work for 0 and -1 and some special values such as 0x01010101... But it would still be a non portable approach as it would fail or even invoke undefined behavior on exotic architectures with padding bits or non 2s complement integer representation.
The correct way to initialize the array is an explicit loop like this:
for (int i = 0; i < length; i++) {
a[i] = 1.0;
}
The compiler will likely compile this loop into very efficient code.
memset sets 1 byte at a time. Because of that, I recommend that you use a custom function to set an array of any data type to a valid value like the following:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void *g_memset(void *dst, void *val, size_t valSize, size_t count);
int main(void)
{
double x = 1.0;
double Array[50];
g_memset(Array, &x, sizeof(x), 20); /* set the 1st 20 elements to 1.0 */
for (int n = 0; n < 20; n++) {
printf("%.1lf ", Array[n]);
}
putchar('\n');
return 0;
}
void *g_memset(void *dst, void *val, size_t valSize, size_t count)
{
char *ptr = (char *)dst;
while (count-- > 0) {
memcpy(ptr, val, valSize);
ptr += valSize;
}
return dst;
}
You use memset to set your every bytes of array a.Double variable are 8 bytes,after memset array a every bytes is 1.
Function memset is for char array.
If you want init your array a you can use a loop(while/for).
int j;
for(j = 0;i < length;j++)
a[j] = 1;

Confusing values when copying to another array

I am trying to copy values from one array to another in C. The original array is of type long int, and it is inputted to the function as *pixel_frequency. The array I want to copy to is temp, and it is a 2D array. However, when I try to copy the values, pixel_frequency is fine but temp gives strange results. Below is the relevant code and some sample output.
Code:
struct node *generate_nodes(long int *pixel_frequency) {
int i;
int temp[max_value + 1][2];
for (i = 0; i < (max_value + 1); i++) {
temp[i][0] = i;
temp[i][1] = pixel_frequency[i];
printf("Frequency for %d is %d\n", temp[i][0], temp[i][1]);
}
...
Output (each frequency is supposed to be 256):
Frequency for 0 is 150160
Frequency for 1 is 256
Frequency for 2 is 256
Frequency for 3 is 256
Frequency for 4 is 255
...
Frequency for 254 is 892677956
Frequency for 255 is 1868789101
Below is an example version of code using your code snippet, take care of the return type and other things.
Instead of using a global variable for array size, you can pass it as a function argument so , it will be easy to identify the size of array you passed.
void generate_nodes(long int *pixel_frequency, size_t size) {
size_t i;
long int temp[size][2];
for (i = 0; i < size; i++) {
temp[i][0] = i;
temp[i][1] = pixel_frequency[i];
printf("Frequency for %ld is %ld\n", temp[i][0], temp[i][1]);
}
}
If you have declared pixel_frequency as a local variable in a function and used the address of array after the variable went out of scope, will lead to undefined behaviour.
int main(void) {
size_t max_len = 5000;
size_t i;
long int* pixel_frequency = malloc(max_len*sizeof(long int));
for( i = 0; i < max_len; ++i) {
pixel_frequency[i] = (i%256);
}
generate_nodes(pixel_frequency, max_len);
return 0;
}

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.

Resources