I want to concatenate two arrays of the same type into a single new array with the same type. But the problem is I have to use void pointers, and somehow my code won't work from the third element on. I searched a bit on the internet but seems like noone is having this problem
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void array_float_fill(float *arr1, float *arr2, int n, int m){
for(int i = 0;i<n;i++){
*(arr1+i)=i+n;
}
for(int i = 0;i<m;i++){
*(arr2+i)=i+m;
}
}
void array_concat(void *arr1, void *arr2, void *arr3, int n, int m,int size){
for(int i=0;i<n;i++){
memcpy((arr3+i),(arr1+i),size);
}
for(int i=0;i<m;i++){
memcpy((arr3+i+n),(arr2+i),size);
}
}
int main(int argc, char const *argv[])
{
int n=10;
int m=10;
float f1[n];
float f2[m];
array_float_fill(f1,f2,n,m);
printf("%f",*(f1+3));
float* f3 = malloc((n+m) * sizeof(float));
array_concat(f1,f2,f3,n,m,sizeof(float));
printf("%f",*(f3+3));
return 0;
}
I tried it with a for-loop to copy every single element to the new array, because the function will just give me a pointer to the start of the array. Dunno why it doesn't work. Any help and hints would be much appreciated
void* pointer arithmetic ...
... is not actually allowed in standard C. gcc allows it and assumes a base operand size of 1. Thus it follows
Index assumption
You are confusing bytes with indexes when using memcpy.
When (non-standardly) adding integer to void pointers, the integer's meaning (in gcc) is that of a byte-offset. This is unlike a typed pointer, there the compiler will do the appropriate scaling for you:
void *p;
int i;
p[i]; // This will be literally p+i after compiling on your compiler
But for example:
float *p;
int i;
p[i]; // This will be p+i*sizeof(float) after compiling.
So instead of ...
for(int i=0;i<n;i++){
memcpy((arr3+i),(arr1+i),size);
}
for(int i=0;i<m;i++){
memcpy((arr3+i+n),(arr2+i),size);
}
... you got to write (this is still compiler-specific):
for(int i=0;i<n;i++){
memcpy((arr3+i*size), (arr1+i*size), size);
}
for(int i=0;i<m;i++){
memcpy((arr3+i*size+n*size), (arr2+i*size), size);
}
... or go standards-conforming:
for(int i=0;i<n;i++){
memcpy((char*)arr3+i*size, (char*)arr1+i*size, size);
}
for(int i=0;i<m;i++){
memcpy((char*)arr3+i*size+n*size, (char*)arr2+i*size, size);
}
By conversion to char*, you enforce a base operand size of 1 byte (more precisely, 1 C byte), which is what you want given the generic nature of your concat function.
However
Note that you can pass arbitrary strides to memcpy, you do not actually need the loops; instead, just do:
memcpy((char*)arr3, arr1, size*n);
memcpy((char*)arr3+n*size, arr2, size*m);
Conversions are only needed where you do arithmetics.
You don't have to memcpy in a loop. If you know the size and the length of the arrays you only need two:
void array_concat(void *arr1, void *arr2, void *arr3, int n, int m,int size)
{
memcpy( arr3 , arr1 , size * n ) ;
memcpy( ( char* )arr3+( size * n ) , arr2 , size * m ) ;
}
The line ( char* )arr3+( size * n ) gives a pointer to the end of the first part.
The cast to char* is needed because pointer arithmetic doesn't work on void*, so we manually increment the pointer to the correct offset.
For example ( char* )arr3+( n ) would not be correct because the underlying type is float. That is why you pass the size of float and then use it.
Your compiler seems to have an extension that allows you to use void* as it were a char* when using pointer arithmetic.Then you increment it incorrectly here: arr3+i just by the value of sizeof( char ),instead of sizeof( float ).
You can copy an entire array with a single memcpy. Check the signature of memcpy:
void *memcpy(void *dest, const void *src, size_t n);
It will copy n contiguous bytes from src to dest, as simple as it sounds. An array is a contiguous block of memory, so you can copy an entire array using a single call to memcpy.
I fixed this and a few other things in the code below:
Access arrays by indices rather than doing pointer arithmetic, which is easy to get wrong.
Constness
Usage of size_t rather than int for sizes and array indices. See Why size_t matters.
It's a good habit to pass the output buffer size and check it prior to any copying in order to prevent buffer overflows.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void array_float_fill(float *arr1, float *arr2, size_t n, size_t m) {
for (size_t i = 0; i<n; i++) {
arr1[i] = i + n;
}
for (size_t i = 0; i<m; i++) {
arr2[i] = i + m;
}
}
void array_concat(
void *out_arr,
size_t out_arr_size,
const void *in_arr1,
size_t in_arr1_size,
const void *in_arr2,
size_t in_arr2_size)
{
const size_t total_size = in_arr1_size + in_arr2_size;
// BE AWARE that `assert` will be gone if you define `NDEBUG`
// (or compile with `-DNDEBUG`).
// This assertion guarantees we have enough space before copying.
assert(out_arr_size >= total_size);
memcpy(out_arr, in_arr1, in_arr1_size);
memcpy((char *)out_arr + in_arr1_size, in_arr2, in_arr2_size);
// The cast to `char *` above is important for portability.
// Arithmetic on a pointer to void is a GNU extension.
// See http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html
}
void dump_array(const char *name, float *array, size_t num_elems) {
printf("%s = ", name);
for (size_t i = 0; i < num_elems; i++) {
printf("%f ", array[i]);
}
printf("\n");
}
int main() {
const size_t n = 10;
const size_t m = 10;
float f1[n];
float f2[m];
array_float_fill(f1, f2, n, m);
const size_t f3_size = (n + m) * sizeof(float);
float *f3 = malloc(f3_size);
array_concat(f3, f3_size, f1, sizeof(f1), f2, sizeof(f2));
// Show the results
dump_array("f1", f1, n);
dump_array("f2", f2, m);
dump_array("f3", f3, n + m);
return 0;
}
Arithmetic operations cannot be performed on void pointers. Since void pointers don't have any fixed data type like int or float, thus they don't know with what value they should get incremented or decrement upon arithmetic operations. For example, when you increment integer pointer, the value is automatically increased by 4 upon every increment. Similarly character pointer will be incremented by 1 upon every increment. Here in your example, when memcpy operation trying to copy the value from arr1 to arr3, it can't be able to de-reference arr3, hence the problem. Generally whenever any such operations performed on void pointers, first they need to be de-referenced. De-reference it to floating pointer will work, see below
memcpy(((float*)arr3+i),((float*)arr1+i),size);
memcpy(((float*)arr3+i+n),((float*)arr2+i),size);
Try the following
void array_concat( const void *arr1, const void *arr2, void *arr3, int n, int m, int size )
{
memcpy( arr3, arr1, n * size );
memcpy( ( char * )arr3 + n * size, arr2, m * size );
}
Here is how the program can look
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void array_float_fill( float *arr1, float *arr2, size_t n, size_t m )
{
for ( size_t i = 0; i < n; i++ )
{
*( arr1 + i ) = i + n;
}
for ( size_t i = 0; i < m; i++ )
{
*( arr2 + i ) = i + m;
}
}
void array_concat( const void *arr1, const void *arr2, void *arr3,
size_t n, size_t m, size_t size )
{
memcpy( arr3, arr1, n * size );
memcpy( ( char * )arr3 + n * size, arr2, m * size );
}
int main( void )
{
size_t n = 10;
size_t m = 10;
float f1[n];
float f2[m];
array_float_fill( f1, f2, n, m );
printf( "%f\n",*( f1 + 3) );
float *f3 = malloc( ( n + m ) * sizeof( float ) );
array_concat( f1, f2, f3, n, m, sizeof( float ) );
printf( "%f\n", *( f3 + 3 ) );
free( f3 );
return 0;
}
The output is
13.000000
13.000000
Do not forget to free the dynamically allocated array. Also you should include header <string.h> where memcpy is declared.
Take into account that this declaration of main
int main(int argc, char const *argv[])
is wrong.
The correct declaration looks like
int main(int argc, char *argv[])
Related
The following code gives me a terminated by signal SIGSEGV (Address boundary error):
void rec(int x, int *arr, int *size) {
if (x < 0) {
rec(-x, arr, size);
return;
}
arr = realloc(arr, sizeof(int) * ++(*size));
*(arr + (*size) - 1) = x % 10;
if (x % 10 != x)
rec(x / 10, arr, size);
}
int main() {
int *arr = malloc(sizeof(int));
int *size = malloc(sizeof(int));
*size = 0;
rec(20, arr, 0);
}
I already figured our that the arr counter in the main method won't hold the desired result, but I still can't understand why I'm getting an error.
Notice that you are passing NULL as third argument:
rec(20, arr, 0); // 0 is NULL
and you get a segfault dereferencing it:
arr = realloc(arr, sizeof(int) * ++(*size)); // here size is `NULL`
try with
rec(20, arr, size);
For starters these memory allocations
int *arr = malloc(sizeof(int));
int *size = malloc(sizeof(int));
does not make a sense. They are redundant.
You could just write
int *arr = NULL;
size_t size = 0;
Secondly the variable size is declared but not used because instead of the variable you passed the integer constant 0
rec(20, arr, 0);
So within the function rec
void rec(int x, int *arr, int *size);
the pointer size was initializer by the null pointer constant 0. That is size is a null pointer within the function and using a null pointer to access memory results in undefined behavior.
Also you should pass the pointer to the function by reference. Otherwise passing it to the function does not make a great sense because the pointer in main will not be changed.
The code in main could look like
int *arr = NULL;
size_t size = 0;
rec( 20, &arr, &size );
Pay attention to that you should free all the allocated memory when it will not be used any more.
Correspondingly the function should be declared like
void rec(int x, int **arr, size_t *size);
Use the type size_t instead of the type int because this unsigned integer type is the type of the second argument of the function realloc.
In general to get the result of realloc you should use an intermediate variable because the function can return a null pointer and the current pointer will be lost.
Also pay attention to that the call of the function is unsafe and can result in an infinite recursion due to this if statement
if (x < 0) {
rec(-x, arr, size);
return;
}
when the user passes to the function the value of x equal to INT_MIN.
Consider the following demonstrative program.
#include <stdio.h>
#include <limits.h>
int main(void)
{
int x = INT_MIN;
printf( "x = %d\n", x );
printf( "-x = %d\n", -x );
return 0;
}
Its output might look like
x = -2147483648
-x = -2147483648
As you can see negating the value of the variable x you get the same negative value. So maybe it is better to declare the first function parameter as having the type unsigned int.
Your function can look for example the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
int rec( unsigned int x, unsigned int **arr, size_t *size )
{
const unsigned int Base = 10;
unsigned int *tmp = realloc( *arr, sizeof( int ) * ++*size );
int success = tmp != NULL;
if ( success )
{
*arr = tmp;
*( *arr + *size - 1 ) = x % Base;
if ( x % Base != x )
{
success = rec( x / Base, arr, size );
}
}
return success;
}
int main(void)
{
unsigned int *arr = NULL;
size_t size = 0;
rec( 123456789, &arr, &size );
for ( size_t i = 0; i < size; i++ )
{
printf( "%u", *( arr + i ) );
}
putchar( '\n');
free( arr );
return 0;
}
The program output is
987654321
I created an insertion sort method which accepts an array, its size and a comparator. The comparator function is this:
int compare_int_ptr(void* ptr1, void* ptr2) {
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
if(i1<i2) {
return -1;
}
if(i1 == i2) {
return 0;
}
return 1;
}
The insertion is this:
void insertion_sort(void** array, int size, CompFunction compare){
int i,j;
void* key;
for(i = 1; i<size;i++){
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
swap(&array[j+1],&array[j]);
}
array[j+1] = key;
}
}
If I try to execute it, I get the segmentation fault error, so I think that I didn't used the pointer correctly. Is it correct that when I do the swap i pass it with the &?
EDIT: this is where I call the method:
int main(int argc, char const *argv[]) {
if(argc < 2) {
printf("Usage: sortingfirstusage <file_name>\n");
exit(EXIT_FAILURE);
}
double* array = load_array(argv[1]);
insertion_sort((void**)array, 3, compare_int_ptr);
free(array);
return 0;
The array is correctly loaded because I printed all the elements before calling the insertion sort and they were in.
You are trying to sort an array of doubles. double *array points to the first of n elements:
array ==> [ double ] \
[ double ] |
. > n elements
. |
[ double ] /
You are casting array to a void **:
(void **)array ==> [ void * ] \
[ void * ] |
. > n elements
. |
[ void * ] /
It should not be hard to determine that trouble lies ahead. A void * is not a double. It may or may not be the same size as a double. It almost certainly doesn't point to a valid memory location, so if you dereference it you will invoke undefined behavior, almost certainly resulting in your program being killed by a signal. Unfortunately, your insertion_sort function does dereference it when it calls the comparison function:
key = array[i];
for(j = i-1; j>=0 && compare(array[j],key)>=0;j--){
array[i] and array[j] are both invalid void * values (because the underlying memory contains doubles, not void *s). Your comparison function dereferences them here:
double i1 = *(double*)ptr1;
double i2 = *(double*)ptr2;
ptr1 and ptr2 contain meaningless pointer values. They do not point to doubles. Dereferencing them invokes undefined behavior.
Here is a working version of insertion_sort using the same function type and equivalent functionality to the qsort function from the C standard library (although the function is a lot less efficient than qsort):
insertion_sort.h:
#ifndef INSERTION_SORT_H_INCLUDED__
#define INSERTION_SORT_H_INCLUDED__
#include <stddef.h>
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
#endif
insertion_sort.c:
#include <string.h>
#include "insertion_sort.h"
void insertion_sort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
char (*b)[size] = base;
size_t i;
size_t j;
int cmp;
for (i = 1; i < nmemb; i++) {
j = i - 1;
/* search backwards for insertion point */
while ((cmp = compar(b + j, b + i)) > 0 && j > 0)
j--;
if (cmp <= 0)
j++; /* went back one too far */
if (j < i) {
/* rotate element i to position j, j to j+1, ..., i-1 to i */
char tmp[size];
memcpy(&tmp[0], &b[i][0], size);
memmove(&b[j + 1][0], &b[j][0], size * (i - j));
memcpy(&b[j][0], &tmp[0], size);
}
}
}
Here is an example of the usage of the above function:
main.c:
#include <stdio.h>
#include "insertion_sort.h"
int compar_double(const void *a, const void *b)
{
double d1 = *(const double *)a;
double d2 = *(const double *)b;
if (d1 < d2)
return -1;
if (d1 > d2)
return 1;
return 0;
}
void print_doubles(const double *d, size_t n)
{
size_t i;
for (i = 0; i < n; i++)
printf("%g\n", d[i]);
}
int main(void)
{
double numberlist[] = { 3.0, 1.0, 5.0, -4.0, 2.0 };
size_t len = sizeof numberlist / sizeof numberlist[0];
printf("Unsorted:\n");
print_doubles(numberlist, len);
printf("\n");
insertion_sort(numberlist, len, sizeof numberlist[0], compar_double);
printf("Sorted:\n");
print_doubles(numberlist, len);
return 0;
}
Here is the output produced by the above program:
Unsorted:
3
1
5
-4
2
Sorted:
-4
1
2
3
5
void qsort( void *ptr, size_t count, size_t size,
int (*comp)(const void *, const void *) );
Like qsort, your sorting function should take a void * as the first parameter, not void **. The double indirection is a mistake that you should have noticed when calling insertion_sort. Converting a double[] array to void ** requires a cast, whereas it can be converted automatically to void * without one.
Without knowing what load_array(argv[1]); does, the answer is impossible to predict as Peter suggested in the comments.
Assuming this function call is doing something legitimate and loading the array with pointers that can be de-referenced properly then your problem is the cast. You cannot make a pointer into a pointer to pointers. You have to pass the address of the pointer to accomplish what you want.
insertion_sort(&array, 3, compare_int_ptr);
So, what I'm trying to achieve here, is to use the C implementation of qsort in a 2d array, in witch I want only the rows to be sorted based on the its first element, for example:
int arr[3][2]={{65,1},
{45,2},
{66,3}}
I want the output to be:
int arr[3][2]={{45,2},
{65,1},
{66,3}}
Is there a way of doing this without implementing quicksort myself? If so, how?
EDIT
This is what my code looks like:
int f(int a, int b)
{
return a-b;
}
qsort(arr[0],3,sizeof(int),f);
You're not sorting integers, you're sorting "things" that happen to be a number of integers in size.
So, don't lie to qsort() about your element size:
#include <stdio.h>
#include <stdlib.h>
static int cmprow(const void *a, const void *b)
{
const int * const ia = a, * const ib = b;
return ia[0] < ib[0] ? -1 : ia[0] > ib[0];
}
int main(void) {
int arr[3][2]={{65,1},
{45,2},
{66,3}};
qsort(arr, sizeof arr / sizeof *arr, sizeof *arr, cmprow);
for (size_t i = 0; i < sizeof arr / sizeof *arr; ++i)
{
for (size_t j = 0; j < sizeof *arr / sizeof **arr; ++j)
printf("%d ", arr[i][j]);
putchar('\n');
}
return 0;
}
This prints:
45 2
65 1
66 3
Here is the problem:
qsort(arr[0],3,sizeof(int),f);
This function take size_t as the second argument. You have passed 3. Thats not the size, thats count of elements in the array arr. In a crude way, you need something like 3*sizeof(int). Or better sizeof(arr) / sizeof *arr.
So, change it to
qsort(arr, sizeof(arr) / sizeof *arr, sizeof(int), sizeof *arr, comparator);
With:
int comparator(const void *p, const void *q)
{
// Get the values at given addresses
int l = *(const int *)p;
int r = *(const int *)q;
// both odd, put the greater of two first.
if ((l&1) && (r&1))
return (r-l);
// both even, put the smaller of two first
if ( !(l&1) && !(r&1) )
return (l-r);
// l is even, put r first
if (!(l&1))
return 1;
// l is odd, put l first
return -1;
}
I have code like:
#include <stdio.h>
#include <stdlib.h>
void mad(int ***, int, in);
int main(void) {
int **x;
int n,m;
scanf("%d%d",&n,&m);
mad(x,n,m);
x[0][0] = 5;
printf("%d\n",x[0][0]);
return 0;
}
void mad(int ***x, int n, int m) {
int i;
**x = malloc(sizeof(int *));
for (i = 0; i < n; i++)
***(x + i) = malloc(m * sizeof(int));
}
This is wrong can someone explain why this is wrong and help me to get it right.
You need to have a variable which is a pointer to a pointer, so declare it as such:
int **x;
but if you want another function to assign it a value, you need to pass a pointer to that variable, so declare a function as
void mad(int ***x,int n, int m);
call it with passing a pointer to the variable:
mad(&x,m,n);
and assign a new value to the dereferenced pointer
void mad(int ***x,int n, int m)
{
*x = malloc(...);
}
BTW, the first malloc call seems incorrect – you allocate the block of memory big enough to keep a single pointer to int while it probably should be n pointers to int:
*x = malloc(n*sizeof(int *));
Then allocate your n array's rows, each m ints long:
for (i=0; i<n; i++)
*(*x + i) = malloc(m*sizeof(int));
*x ìs an pointer to a pointer to an array. malloc(n * sizeof(int*)); allocates an array of pointers. *(*x+i) or (*x)[i] is an array. malloc(m * sizeof(int)); allocates an array. Adapt your code like this:
void mad(int ***x, int n, int m){
int i;
*x = malloc(n * sizeof(int*)); // allocate memory where x refers to
for( i=0; i<n; i++ )
*(*x+i) = malloc(m * sizeof(int)); // similar to (*x)[i] = malloc(m * sizeof(int))
}
mad(&x,n,m);
// ^
You should avoid all of those inefficient pointer-to-pointer based lookup tables. They are not arrays since they are not allocated in adjacent memory cells.
Allocate a real 2D array instead:
void alloc2d ( size_t x, size_t y, int(**ptr)[x][y] )
{
*ptr = malloc ( sizeof(int[x][y]) );
}
int main (void)
{
const int x = 5;
const int y = 3;
int (*arr_ptr)[x][y];
alloc2d(x, y, &arr_ptr);
int (*array2d)[y] = *arr_ptr; // point at 1st element which is an array
array2d[i][j] = something;
...
free(arr_ptr);
}
I created a generic matrix structure like this:
typedef struct mat_t {
/**
* \brief matrix structure
*/
unsigned int c, l;
void **matrice;
}* mat;
My problem is to learn how to allocate memory for the matrix because it can contain complex numbers, float numbers or others...
Thus, I want to know how to pass a type to my function argument for allocation memory.
mat allocate_mat(unsigned int l, unsigned int c, **<type>** )
Maybe, should I use a define macro for this function?
Maybe, should I use a define macro for this function ?
Yes, you can define a macro to take a type in the last parameter, and call the real function which takes a size in the last parameter.
#define allocate_mat(MAT_L, MAT_C, MAT_TYPE) allocate_mat_sz(MAT_L, MAT_C, sizeof(MAT_TYPE))
mat allocate_mat_sz (unsigned l, unsigned c, size_t size);
Problem 1: weird variable names. What are l and c supposed to mean? "Lines", "count"? There is nothing in C preventing you from using full words as variable names...
Problem 2: you are most likely using a false would-be 2D array, with pointer-to-pointer notation, which results in a heap fragmentation fiasco. Not only is it slow and leads to heap fragmentation, it also can't be used with fundamental C functions like memset(), memcpy(). Allocate a true 2D array instead, in adjacent memory.
Problem 3: Why do you have * mat at the end of the struct typedef? It doesn't make any sense.
Here is a basic implementation of a dynamic matrix, using generic C programming:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct mat_t
{
void** data;
size_t row_n;
size_t col_n;
size_t obj_size;
} matrix_t;
bool matrix_init (matrix_t* mat,
size_t row_n,
size_t col_n,
size_t obj_size)
{
mat->row_n = row_n;
mat->col_n = col_n;
mat->obj_size = obj_size;
mat->data = calloc(row_n * col_n, obj_size);
return mat->data != NULL;
}
void matrix_free (matrix_t* mat)
{
free(mat);
}
void matrix_set (matrix_t* mat,
size_t x,
size_t y,
void* val)
{
size_t data_offset = y * mat->row_n * mat->obj_size +
x * mat->obj_size;
memcpy (mat->data + data_offset,
val,
mat->obj_size);
}
void* matrix_get (const matrix_t* mat,
size_t x,
size_t y)
{
size_t data_offset = y * mat->row_n * mat->obj_size +
x * mat->obj_size;
return mat->data + data_offset;
}
int main()
{
matrix_t mat;
const int ROWS=3;
const int COLS=2;
// allocate memory
matrix_init(&mat, ROWS, COLS, sizeof(int));
// fill memory with data 1,2,3...
int count =0;
for(int row=0; row<ROWS; row++)
{
for(int col=0; col<COLS; col++)
{
count++;
matrix_set (&mat, row, col, &count);
}
}
// print the matrix
for(int row=0; row<ROWS; row++)
{
printf("[ ");
for(int col=0; col<COLS; col++)
{
printf("%d ", *(int*)matrix_get(&mat, row, col));
}
printf("]\n");
}
matrix_free(&mat);
return 0;
}
You can pass size of matrix element:
mat allocate_mat(unsigned int l, unsigned int c, unsigned int size_of_matrix_element )