0

I am slowly learning how to program generic functions in C and get into trouble now and so often. I am making a program that makes a union of two arrays, in this implementation two int arrays. The first problem, which also leads to the second one, is that the compareints (function) does not access one of the passed arguments (void *): I can't figure out why? I been staring at the screen for to long time now...

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

//makes union of two generic arrays and eliminates duplicates if there are some...
void **
unite(int (*comp)(void *f, void *s), void **first, void **second, int f_size, int s_size,     int bytes, int *x)
{
     int i;
     void **arr=malloc(bytes*(f_size+s_size));
     for(i=0; i<f_size+s_size; i++)
     {
         /* first bigger */
         if(((*comp)(*first, *second))>0)
         {
            *(arr+i)=*(first++);
         }
         /* second bigger */
         else if(((*comp)(*first, *second))<0)
         {
            *(arr+i)=*((second++));
         }
         /* equal => just one copy */
         else
         {
            *(arr+i)=*(first++);
            second++;
         }
     }
     *x=i;
     return arr;
 }

 int
 compareints(void *first, void *second)
 {
     if(*((int *)first)>*((int *)second)) //can't access the memoryloc in second...
         return 1;
     else if(*((int *)first)<*((int *)second))
         return -1;
     else
         return 0;
 }

 int main(int argc, const char * argv[])
 {

     int arr[10]={1, 2, 4, 12, 22, 29, 33, 77, 98};
     int arr2[5]={3, 5, 7, 8, 9};
     void **first=malloc(sizeof(int *)*10);
     void **second=malloc(sizeof(int *)*5);
     //make pointers to static arrays in dynamic arrays
     int f_ind, s_ind;
     for(f_ind=0; f_ind<10; f_ind++)
         first[f_ind]=&arr[f_ind];
     for(s_ind=0; s_ind<5; s_ind++)
         second[s_ind]=&arr2[s_ind];
     int i;
     //make union of the two arrays and print out the result
     void **ret=unite(&compareints, first, second, 10, 5, sizeof(int), &i);
     for(int k=0; k<i; k++)
         printf("%d  ", *((int *)ret[k]));
     return 0;
 }
patriques
  • 5,057
  • 8
  • 38
  • 48
  • Didn't you ask this same question earlier? [how to initialize generic functions in c](http://stackoverflow.com/questions/13617168/how-to-initialize-generic-functions-in-c) – Nocturno Nov 29 '12 at 04:58
  • @Nocturno well, I see the resemblance between my questions but they are different. – patriques Nov 29 '12 at 05:02
  • 1
    Btw, your code crashes in `unite()` when the for-loop reaches `5`, and it should be blatantly obvious why. – WhozCraig Nov 29 '12 at 05:14
  • @WhozCraig thanks for pointing that out, I did not see that myself.. Also I found something embarrasing, that the function tries to reverse the order.. yikees – patriques Nov 29 '12 at 05:27

2 Answers2

1
Why can't function access generic parameter ?

Simple answer to this question is function can access but further manipulation on void * is not possible.

Elements are accessed using pointer arithmetic (which needs size of individual element) since the pointer which is void * pointing to the address you passed but doesn't know about the size of each field in that array or memory location. so accessing or dereferencing will lead you to Undefined Behaviour.

If you want to access each element of that type inside the function then , pass the size of individual element to that function and on that basis make pointer to that same type , then access using new pointer of that type.

For more read this

Community
  • 1
  • 1
Omkant
  • 9,018
  • 8
  • 39
  • 59
0

I tried an approach thanks to @WhozCraigs post about the index going out of bounds. So I made some small mods and now the program does what it intends to.

void **
unite(int (*comp)(void *f, void *s), void **first, void **second, int f_size, int s_size, int bytes, int *x)
{
    int i;
    int f_ind=0, s_ind=0;
    void **arr=malloc(bytes*(f_size+s_size));
    for(i=0; i<f_size+s_size; i++)
    {
        /* first bigger */
        if(((*comp)(*first, *second))>0)
        {
            s_ind++;
            if(s_ind<s_size)
                *(arr+i)=*(second++);
            else
            {
                f_ind++;
                if(f_ind<f_size)
                    *(arr+i)=*(first++);
                else
                    break;
            }
        }
         /* second bigger */
        else if(((*comp)(*first, *second))<0)
        {
            f_ind++;
            if(f_ind<f_size)
                *(arr+i)=*(first++);
            else
            {
                s_ind++;
                if(s_ind<s_size)
                    *(arr+i)=*(second++);
                else
                    break;
            }
        }
        /* equal => just one copy */
        else
        {
            f_ind++;
            s_ind++;
            if(f_ind<f_size && s_ind==s_size)
            {
                *(arr+i)=*(first++);
            }
            else if(f_ind==f_size && s_ind<s_size)
            {
                *(arr+i)=*(second++);
            }
            else
            {
                *(arr+i)=*(first++);
                second++;
            }  
        }
    }
    *x=i;
    return arr;
}
patriques
  • 5,057
  • 8
  • 38
  • 48