1

I'm working for the first time with generic types in C and I'm having some problems with my code. My compiler works but when I run my program it prints strange characters.

I have a library with functions that works on generic types of array (insertion and quick sort) and I want to test my library.

I summed up my code with this little example so you don't have to read my whole code. The char_function is the generic function that I want to test in this case and in my main I've the test. I expect this output:

b
c
c

The code:

#include <stdio.h>
#include <stdlib.h>

void generic_function(void** array);

int main(){
  char* ch= (char*)malloc(sizeof(char)*3);
  ch[0] = 'a';
  ch[1] = 'b';
  ch[2] = 'c';
  generic_function((void**)ch);
  printf("%c\n", ch[0]);
  printf("%c\n", ch[1]);
  printf("%c\n", ch[2]);
  return 0;
}

void generic_function(void** array){
  array[0] = array[1];
  array[1] = array[2];
}
  • `ch[0]` is a char while `((void**)ch)[0]` is a `void*` so the cast doesn't make sense. Maybe you should start by spelling out what the code is supposed to do. – dxiv May 06 '20 at 15:47
  • i edited my code @dxiv – Riccardo Rosso May 06 '20 at 15:57
  • `(void**)ch` --> `(void**)(&ch)` – user12986714 May 06 '20 at 16:03
  • @user12986714 I tried but it doesn't work... – Riccardo Rosso May 06 '20 at 16:06
  • @user12986714 No, that does not make any difference at all, see [here](https://stackoverflow.com/questions/2528318/how-come-an-arrays-address-is-equal-to-its-value-in-c) for example. – dxiv May 06 '20 at 16:07
  • Because you need to adjust your function accordingly. First, you cannot guarantee sizeof(char)==sizeof(void), and also that array[0] is a `void *` and hence makes no sense. To fix it, first do `char **tmp; tmp=array;` and then use `(*tmp)[0]` instead of `array[0]` – user12986714 May 06 '20 at 16:08
  • @RiccardoRosso The standard [qsort](https://en.cppreference.com/w/c/algorithm/qsort) comparator function would not take `void**` arguments (but rather just `const void*`). If your library uses some other convention you'll need to refer to its docs for how it works, or if it even works with arrays of non-pointer types. – dxiv May 06 '20 at 16:08
  • @user12986714 but if I use char **tmp it means that i know what type i'm using in the generic_function but it is generic, i don't know what type i'll use in my input, it can be int, char,... – Riccardo Rosso May 06 '20 at 16:12
  • You either need to pass some metadata about what type it is, say pass sizeof(char) as a parameter, or you have to hardcode that. It is impossible to avoid, as say if you can pass both int array and char array, intarr[3] would be *(intarr+3*sizeof(int)), while chararr[4] would be *(chararr+4*sizeof(char)) while sizeof(int)!=sizeof(char), and the function has no knowledge whether you passed a char or int array. – user12986714 May 06 '20 at 16:16
  • @RiccardoRosso Bottom line is that you can't have the *same* C code perform cell level operations on an array of `char` and an array of `void*`, because the `sizeof` cells is different between the two. How you "package" that depends on the API of the library you use. – dxiv May 06 '20 at 16:17
  • OT: regarding: `char* ch= (char*)malloc(sizeof(char)*3);` 1) the returned type is `void*` which can be assigned to any pointer. Casting just clutters the code and is error prone. Suggest removing the cast. 2) the expression: `sizeof(char)` is defined in the C standard as 1. Multiplying anything by 1 has no effect and just clutters the code. Suggest removing that expression. (cont) – user3629249 May 06 '20 at 17:19
  • (cont) 3) always check (!=NULL) the returned value to assure the operation was successful. If not successful, the call `perror( "malloc failed" );` to output both the error message "maloc failed" and the text reason the system thinks the error occurred to `stderr`. – user3629249 May 06 '20 at 17:20
  • thank you everyone, really kind! @dxiv – Riccardo Rosso May 06 '20 at 17:20
  • thank you! @user3629249 – Riccardo Rosso May 06 '20 at 17:21

0 Answers0