How can I concatenate two arrays in C using memcpy? - c

I have 2 arrays with coordinates and i want to copy them into one array. I used 2 for loops and its working, but i want to know, if i could do it without them, i dont know how to use memcpy in this situation. Here is my code:
int *join(int *first, int *second,int num, int size) {
int *path= NULL;
int i = 0 , j = 0;
path = (int*) malloc (2*size*sizeof(int));
for(i = 0 ; i < num; i++) {
path[i * 2] = first[i * 2];
path[i * 2 + 1] = first[i * 2 + 1];
}
for(i = num; i < size ; i++) {
path[(i*2)] = second[(j+1)*2];
path[(i*2)+1] = second[(j+1)*2 +1];
j++;
}
return path;
}

Just calculate the correct number of bytes to copy and copy from each origin to the correct offset:
int *join(int *first, int *second, int num, int size) {
// Compute bytes of first
const size_t sizeof_first = sizeof(*first) * 2U * num;
// Computes bytes of second as total size minus bytes of first
const size_t sizeof_second = sizeof(int) * 2U * size - sizeof_first;
int *path = malloc(sizeof(int) * 2U * size);
// Copy bytes of first
memcpy(path, first, sizeof_first);
// Copy bytes of second immediately following bytes of first
memcpy(&path[2U * num], second, sizeof_second);
return path;
}

Related

How can I change what a pointer points to within a function in C?

I'm trying to code a resizable array, which expands when it's full. All functions are working, but the resize one isn't.
int main(void)
{
int arr[4];
int *ptr = arr;
initializeEmptyArray(ptr);
insertAtIndex(ptr, 0, 4);
insertAtIndex(ptr, 0, 3);
insertAtIndex(ptr, 0, 2);
insertAtIndex(ptr, 0, 1);
resizeArray(&ptr);
for (int i = 0; i < capacity; i++)
{
printf("%i", arr[i]);
}
}
This initiates my array [1,2,3,4] and then calls the resize array to test it.
void resizeArray(int **arr)
{
int *newArr = (int *)malloc(capacity * 2 * sizeof(int));
for (int i = 0; i < capacity; i++)
{
newArr[i] = (*arr)[i];
}
for (int i = capacity; i < capacity * 2; i++)
{
newArr[i] = EMPTY;
}
free(*arr);
*arr = newArr;
}
The problem is the value of arr when I print it doesn't change to [1,2,3,4,-1,-1,-1,-1] (-1 represents empty). How can I change the pointer to point to this new array?
Capacity stands for the number of elements the array support, initiated as 4
EMPTY is defined as -1, to represent a empty slot in the array.
The two main issues with the code is that arr is allocated on the stack in main(), and then you free() it in resizerArray(). That is a defect, and I fixed that my heap allocating arr in main() instead. In your loop, you print arr[i] but pass ptr to resizeArray() which is updated, but arr still points to memory that is now free'ed. I fixed this issue by eliminated the ptr variable:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EMPTY 0
void resizeArray(int **arr, size_t capacity) {
int *newArr = malloc(2 * capacity * sizeof(int));
// for (int i = 0; i < 2 * capacity; i++) {
// newArr[i] = i < capacity ? (*arr)[i] : EMPTY;
// }
memcpy(newArr, *arr, capacity * sizeof(int));
memset(newArr + capacity, EMPTY, capacity * sizeof(int));
free(*arr);
*arr = newArr;
}
int main(void) {
size_t capacity = 4;
int *arr = malloc(capacity * sizeof(int));
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
for (int i = 0; i < capacity; i++) {
printf("before: %d\n", arr[i]);
}
resizeArray(&arr, capacity);
capacity *= 2;
for (int i = 0; i < capacity; i++) {
printf("after: %d\n", arr[i]);
}
}
I comment out the loop in resizeArray so you can see how you would do that. The code prints:
before: 1
before: 2
before: 3
before: 4
after: 1
after: 2
after: 3
after: 4
after: 0
after: 0
after: 0
after: 0
Both resizeArray() and the calling code has to know about the factor 2. This is not a great design. Maybe pass in old and new capacity? Or pass in size_t *capacity that can be updated if you want to hard-code the factor in resizeArray()? Remember to check the return value of malloc() to ensure it did not fail.
See realloc() for the standard way to resize heap allocated memory, and calloc() for how to get pre-initialized memory.
You can't resize an array. It's size is fixed.
So if you want something that can be resized do:
int arr[4]; --> int* arr = malloc(4 * sizeof *arr);
BTW:
It seems you miss a line like:
capacity = 2 * capacity ;
Hava a look at "realloc", your question sounds like a perfect match
You can not resize an array with automatic storage duration. You can do this with arrays that have allocated storage duration.
So you should remove the array declaration in main and write
int *ptr = malloc( 4 * sizeof( int ) );
or
int *ptr = malloc( capacity * sizeof( int ) );
Also you forgot to change the value of the variable capacity. I suppose that it is not declared as a constant variable.
In this case the function resizeArray can look for example the following way
int resizeArray( int **arr )
{
int *newArr = realloc( *arr, capacity * 2 * sizeof(int));
int success = newArr != NULL;
if ( success )
{
*arr = newArr;
for (int i = capacity; i < capacity * 2; i++)
{
newArr[i] = EMPTY;
}
capacity *= 2;
}
return success;
}
Pay attention to that a reallocation of the array can fail. So the function should signal to the caller whether the reallocation was successful.
Also it is not a good idea to use the variable capacity as a global variable.
You could write in main
int capacity = 4;
int *ptr = malloc( capacity * sizeof( int ) );
// ...
and call the function like
resizeArray( &ptr, &capacity );
In this case the function will look the following way
int resizeArray( int **arr, int *capacity )
{
int *newArr = realloc( *arr, *capacity * 2 * sizeof(int));
int success = newArr != NULL;
if ( success )
{
*arr = newArr;
for (int i = *capacity; i < *capacity * 2; i++)
{
newArr[i] = EMPTY;
}
*capacity *= 2;
}
return success;
}

Find the difference between elements in an array and store the results in a new array

This is my current code:
#include <stdio.h>
int index_x[] = {0,0,1,0,1,0,0,0,1,0,0,1,0}; // any number of elements
int len = sizeof index_x / sizeof*index_x;
int main(void) {
int arr[len];
int j = 0;
for (int i = 0; i < len; i++)
if (index_x[i])
arr[j++] = i; // save and advance j only if value is "1"
for (int i = 0; i < j; i++) // only print below j !
printf("%d\n", arr[i]);
}
Output:
2
4
8
11
From this output, I would like to generate another array that is the difference between these elements. In this case the new array would be {2,4,3}. (2-4=2, 8-4=4, 11-8=3).
I am currently struggling with two things:
Saving the array generated from the current code arr[i] as a another array so I can manipulate it for future uses.
Generating the "differences array". The tricky part is that the number of elements will not be constant so I cannot specify an array size.
It may be helpful to break things out into functions.
int indexes_of_non_zero(int *source, size_t len, int **dest) {
*dest = malloc(sizeof(int) * len);
int count = 0;
for (int i = 0; i < len; i++) {
if (source[i] != 0) {
(*dest)[count++] = i;
}
}
*dest = realloc(*dest, sizeof(int) * count);
return count;
}
So we have a function indexes_of_non_zero that takes a source array of ints with size specified by argument len, and then a pointer to an array of ints that will be the destination for our output.
We can naively allocate the same amount of memory to the destination, then loop over the source array and store the indexes of non-zero elements. When we're done, we use count to know the size of destination array. We use realloc to shrink the array to just the needed size. And the key is we return the count so our main function knows how big the destination array is.
We can now create a diffs function to do basically the same thing for the differences.
int diffs(int *source, size_t len, int **dest) {
*dest = malloc(sizeof(int) * (len - 1));
for (int i = 0; i < (len - 1); i++) {
(*dest)[i] = abs(source[i] - source[i + 1]);
}
return len - 1;
}
Putting it all together (not copying and pasting the function implementations for terseness) with a main function, and remembering to free the memory we've used, we get:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int indexes_of_non_zero(int *source, size_t len, int **dest);
int diffs(int *source, size_t len, int **dest);
int main(void) {
int data[] = {0,0,1,0,1,0,0,0,1,0,0,1,0};
size_t len = sizeof(data) / sizeof(*data);
int *nz = NULL;
int *d = NULL;
int nzc = indexes_of_non_zero(data, len, &nz);
int dlen = diffs(nz, nzc, &d);
for (int i = 0; i < nzc; i++) {
printf("%d\n", nz[i]);
}
for (int i = 0; i < dlen; i++) {
printf("%d\n", d[i]);
}
free(nz);
free(d);
}
And compiling and running it, the output is:
2
4
8
11
2
4
3
I changed it to get the differences as direct as possible; the inner loop is very simple.
The size question, first part: I (still) tried to avoid size_t for the input but added some sanity check for the size. Just to show there is a limit.
part two: a first loop to get the sum of true values in advance. Also the booldata array consists of chars and is not called index_x. Index is i.
part three: the diffs VLA gets its exact size, which can be 0 even for huge inputs. Some test could be added here after counting, to rule out a (big) input full of "1".
I added the copying, with message and printout.
#include <stdio.h>
#include <string.h>
char booldata[] = { 0,0,1,0,1,0,0,0,1,0,0,1,0 };
char sz_overf = sizeof booldata > 0xffffL * 0xffff; // too-big-flag for exiting...
int len = sizeof booldata / sizeof * booldata; // ...to keep len below size_t
int sum_of_trues (char *booldata, int len) {
int sum = 0;
for (int i = 0; i < len; i++)
if (booldata[i])
sum++;
return sum;
}
void print_intarr(int *inta, int len) {
for (int i = 0; i < len; i++)
printf("%d\n", inta[i]);
}
int main(void)
{
if (sz_overf) return 100; // len might be overflowed
int unsigned // signed provokes VLA warning: 9 gazillions seems ok, but not 18
dsum = sum_of_trues(booldata, len) - 1; // Invest a counting loop
int diffs[dsum], // VLA
di = 0; // diffs' index
int sti = -1; // Stored last index containing true
for (int i = 0; i < len; i++)
if (booldata[i]) { // true?
if (sti >= 0) { // and is there a left neighbour?
int diff = i - sti; // how far away?
printf("%d\n", diff); // 1. on-the-fly result
diffs[di++] = diff; // 2. for keeps
}
sti = i; // remember last "true"
}
printf("Copying %zu bytes from Diff.-Array\n", sizeof diffs);
int diffscopy[sizeof diffs];
memcpy(diffscopy, diffs, sizeof diffs);
print_intarr(diffscopy, dsum); // dsum or sizeof diffs
return 0;
}
output:
2
4
3
Copying 12 bytes from Diff.-Array
2
4
3
The inner loop could look like this w/o multi-option:
if (booldata[i]) {
if (sti >= 0) // and is there a left neighbour?
diffs[di++] = i - st; // 2. for keeps
sti = i;
}
Two arrays and three variables. The rest is needed to make this work.
BUGS: all-false input segfaults. It takes one "true" to get zero diffs...

Get an Integer value from 4 consecutive bytes in a string

Being given a char array, I have to save in a variable of type int a number that is represented on 4 consecutive bytes in that char array.
I know the position where the first byte is in that array.
What should I do?
Edit:
Solution #1:
int number , offset;
char *data;
memcpy(&number, &data[offset], 4);
Solution #2:
int number , offset;
char *data;
number = *(int*)(data + offset);
// offset: where the first of the four bytes is situated
Not tested
int convert_to_int(chat *buff, int ascii, int str, int endianess)
{
union
{
int i;
unsigned char uc[sizeof(int)];
}ui = {.i = 0};
int mult = 1;
if(str)
{
for(int digit = 0; digit < sizeof(ui.i); digit++)
{
mult *= 10;
}
}
for(size_t index = 0; index < sizeof(int); index++)
{
size_t pos = endianess ? index : sizeof(ui.i) - 1 - index;
if(str)
{
ui.i += mul * (*buff++ - '0');
mul /= 10;
}
else
{
ui[pos] = ascii ? *buff++ - '0' : *buff++;
}
}
return ui.i;
}
This is what I tried to do. It was correct, but I had a wrong offset and I thought the method was wrong. Using memcpy, I got the same result, so I knew which was the problem.
int number , offset;
char *data;
number = *(int*)(data + offset);
// offset: where the first of the four bytes is situated

sort array in C, return sorted indices

I'm using an example from https://phoxis.org/2012/07/12/get-sorted-index-orderting-of-an-array/ where he returns the sort indices from a sort of an array, i.e.
3,4,2,6,8 returns 4,3,1,0,2 (+1 for each index in R). This is the equivalent of R's order function
I've translated his/her code to work as a function returning an array of sorted indices. The code gives the correct answer.
keeping track of the original indices of an array after sorting in C has a similar response, but as #BLUEPIXY warns, his solution doesn't work in all circumstances. I need something that will work in all circumstances, including ties.
however, the original author uses a global pointer, which causes a memory leak, and free() doesn't fix it. which I don't know how to do this without the global pointer.
How can I fix this memory leak, or at least return sorted indices in C that will always work?
#include <stdio.h>
#include <stdlib.h>
/* holds the address of the array of which the sorted index
* order needs to be found
*/
int * base_arr = NULL;
/* Note how the compare function compares the values of the
* array to be sorted. The passed value to this function
* by `qsort' are actually the `idx' array elements.
*/
static int compar_increase (const void * a, const void * b) {
int aa = *((int * ) a), bb = *((int *) b);
if (base_arr[aa] < base_arr[bb]) {
return 1;
} else if (base_arr[aa] == base_arr[bb]) {
return 0;
} else {
// if (base_arr[aa] > base_arr[bb])
return -1;
}
}
int * order_int (const int * ARRAY, const size_t SIZE) {
int * idx = malloc(SIZE * sizeof(int));
base_arr = malloc(sizeof(int) * SIZE);
for (size_t i = 0; i < SIZE; i++) {
base_arr[i] = ARRAY[i];
idx[i] = i;
}
qsort(idx, SIZE, sizeof(int), compar_increase);
free(base_arr); base_arr = NULL;
return idx;
}
int main () {
const int a[] = {3,4,2,6,8};
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
b = order_int(a, sizeof(a) / sizeof(*a));
for (size_t i = 0; i < sizeof(a)/sizeof(*a); i++) {
printf("b[%lu] = %d\n", i, b[i]+1);
}
free(b); b = NULL;
return 0;
}
A straightforward approach without using a global variable can look the following way
#include <stdio.h>
#include <stdlib.h>
int cmp_ptr(const void *a, const void *b)
{
const int **left = (const int **)a;
const int **right = (const int **)b;
return (**left < **right) - (**right < **left);
}
size_t * order_int(const int *a, size_t n)
{
const int **pointers = malloc(n * sizeof(const int *));
for (size_t i = 0; i < n; i++) pointers[i] = a + i;
qsort(pointers, n, sizeof(const int *), cmp_ptr);
size_t *indices = malloc(n * sizeof(size_t));
for (size_t i = 0; i < n; i++) indices[i] = pointers[i] - a;
free(pointers);
return indices;
}
int main( void )
{
const int a[] = { 3,4,2,6,8 };
const size_t N = sizeof(a) / sizeof(*a);
size_t *indices = order_int(a, N);
for (size_t i = 0; i < N; i++) printf("%d ", a[indices[i]]);
putchar('\n');
free(indices);
return 0;
}
The program output is
8 6 4 3 2
As for the memory leak then it is due to overwriting the value of the pointer to redundantly allocated memory.
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
b = order_int(a, sizeof(a) / sizeof(*a));
The memory allocation does not make sense.
The problem I see is that within main function - you are allocating pointer b some memory -
int * b = malloc(sizeof(int) * sizeof(a) / sizeof (*a));
The next line calls order_int(...) that returns a pointer to already allocated memory -
b = order_int(a, sizeof(a) / sizeof(*a));
Looking at the order_int function -
int * order_int (const int * ARRAY, const size_t SIZE) {
int * idx = malloc(SIZE * sizeof(int));
base_arr = malloc(sizeof(int) * SIZE);
for (size_t i = 0; i < SIZE; i++) {
base_arr[i] = ARRAY[i];
idx[i] = i;
}
qsort(idx, SIZE, sizeof(int), compar_increase);
free(base_arr); base_arr = NULL;
return idx;
}
.. you see that idx has been already been allocated the correct memory.
I would suggest removing the malloc from b - see below.
int * b = NULL;

Dynamic multidimensional array on the heap

I want to create a function which can allocate a multidimensional array on the heap with only one call to malloc. (Pointer array) So a function call would look like this:
size_t dim[2] = {2, 4};
int **_2darray = alloc_array(sizeof(int), dim, 2);
// ^ should be the "same" as:
int __2darray[2][4];
What I have so far is the SIZE computation of the whole block needed to hold the array and the pointers:
void *alloc_array(size_t element_size, size_t dimensions[static 1], size_t ndims)
{
unsigned char *DATA = NULL;
size_t SIZE = 0;
size_t multiplicators[ndims];
// Calculate for each dimension the multiplier
// SIZE 3d array: (N1 * sizeof(T **) + (N1 * N2 + sizeof(T *) + (N1 * N2 * n3 + sizeof(T))
// ^- first mulitplier ^ second multiplier ^ third multiplier
for (size_t i = 0; i < ndims; ++i) {
multiplicators[i] = dimensions[i];
for (size_t j = 0; j < i; ++j) {
multiplicators[i] *= dimensions[j];
}
}
SIZE = 0;
for (size_t dimI = 0; dimI < ndims; ++dimI) {
size_t mulval = multiplicators[dimI];
// The elements are in the "last" dimension
if (dimI+1 == ndims) {
SIZE += element_size * mulval;
} else {
// All other elements are pointers to the specific element
SIZE += sizeof(void *) * mulval;
}
}
DATA = malloc(SIZE);
return DATA;
}
So by now the SIZE calculation works. But now I'm stuck with setting the pointers to the right element. I know it's easy with dealing with static dimensions but I want this to be done with dynamic dimensions.
#include <stdlib.h>
#include <stdio.h>
void fill_array_pointers (void** pointers, char* elements,
size_t element_size, size_t total_elements_size,
size_t dimensions[], size_t ndims)
{
if (ndims == 2)
{
size_t i;
for (i = 0; i < dimensions[0]; ++i)
{
pointers[i] = elements + i * element_size * dimensions[1];
}
}
else
{
size_t i;
size_t block_size = total_elements_size / dimensions[0];
for (i = 0; i < dimensions[0]; ++i)
{
pointers[i] = pointers + dimensions[0] + i * dimensions[1];
fill_array_pointers (pointers + dimensions[0]
+ i * dimensions[1],
elements + block_size * i,
element_size, block_size,
dimensions+1, ndims-1);
}
}
}
void* alloc_array (size_t element_size, size_t dimensions[],
size_t ndims)
{
size_t total_elements_size = element_size;
int i;
// total size of elements
for (i = 0; i < ndims; ++i)
total_elements_size *= dimensions[i];
// total size of pointers
size_t total_pointers_size = 0;
int mulval = 1;
for (i = 0; i < ndims-1; ++i)
{
total_pointers_size += dimensions[i] * sizeof(void*) * mulval;
mulval *= dimensions[i];
}
size_t total_size = total_pointers_size;
size_t oddball = total_pointers_size % element_size;
// really needs to be alignof but we don't have it
if (oddball) total_size += (element_size - oddball);
total_size += total_elements_size;
void* block = malloc (total_size);
void** pointers = block;
char* elements = (char*)block + total_size - total_elements_size;
fill_array_pointers (pointers, elements, element_size,
total_elements_size, dimensions, ndims);
return block;
}
Test drive:
int main ()
{
size_t dims[] = { 2, 3, 4 };
int*** arr = alloc_array(sizeof(int), dims, 3);
int i, j, k;
for (i = 0; i < dims[0]; ++i)
for (j = 0; j < dims[1]; ++j)
for (k = 0; k < dims[2]; ++k)
{
arr[i][j][k] = i*100+j*10+k;
}
for (i = 0; i < dims[0]*dims[1]*dims[2]; ++i)
{
printf ("%03d ", (&arr[0][0][0])[i]);
}
printf ("\n");
free (arr);
}
This will not work for multidimensional char arrays on systems where sizeof(char*) != sizeof(char**); such systems exist but are rare. Multidimensional char arrays are pointless anyway.
The test runs cleanly under valgrind.
This is more an intellectual exercise than anything else. If you need maximum performance, don't use arrays of pointers, use a flat array and ugly but efficient explicit index calculations. If you need clear and concise code, you are probably better off allocating each level separately.

Resources