Generic function to print an array in C

2.9k Views Asked by At

I'm trying to write a generic function to print the elements of an array. This is what I have:

void printArray(void * source, int numElements, int size, void (*printFunction)(void *)){

     void *dest[numElements];
     memcpy(dest, &source, (size * nElem));
     int i;
     for (i = 0; i < numElements; i++){
         printFunction(dest[i]);
     }
 }

I am passing in the address of an array, the number of elements in the array, the size of each element in the array, and a callback function to handle printing/formatting for whichever type of array it is (the printing function works fine, I've tested it).

Right now it's printing out the first element, then I'm getting a segmentation fault. I'm having trouble figuring out what the problem is - any help would be greatly appreciated. I'm new to stackoverflow so let me know if I can improve my question.

5

There are 5 best solutions below

10
On BEST ANSWER

Why are you copying at all?

What you actually want is to pass a char pointer, that way you can increment it by size from 0 to numElements times, passing it to printFunction each time.

Notice, you've actually written a more general function than something that just prints an array. You're effectively writing a 'map' function that maps a function on to an array.

Something like this should work (note it's untested):

void printArray(void * source, int numElements, int size, void (*printFunction)(void *)){
    int i;
    for (i = 0; i < numElements; i++){
        printFunction(((char *)source) + i * size);
     }
}
0
On

I'm assuming that source is a void * to the start of the array (not to an array of pointers). In that case...

There's no need to copy the array -- you can just work with source itself. And since modifying function arguments in C is allowed and only affects the copy within the function, you can alter source and numElements as you proceed through the array. With those points in mind, you can simplify your function to the following:

void printArray(void *source, int numElements, 
                    int size, void (*printFunction)(void *))
{
    for (; numElements; numElements--) {
        printFunction(source);
        source = ((char *)source) + size;
    }
}

The version above runs a for loop, decrementing numElements to give one pass per array element. At the end of each pass, source is offset by size to get to the next element, after passing it to your callback function. The (char *) cast is used to allow the pointer arithmetic even though source is a void *.

0
On
void printArray(void * source, int numElements, int size, void (*printFunction)(void *)){
    int i;
    for (i = 0; i < numElements; i++){
        printFunction((source + i * size));
    }
}

In your program you are saving source content to array of void pointers so you are getting segfault when you are printing. Instead you can directly using source, in order to fetch each element you have to add size to source.

0
On

You should be using a char array to alias your data, not a void* array. The latter is an array of pointers, which isn't a suitable type for a buffer.

A generic function should look more like this:

void printArray(void * source, int numElements, int size, void (*printFunction)(void *)){

     char dest[numElements*size];
     memcpy(dest, source, (size * numElements)); // source is already a pointer, don't address it
     int i;
     for (i = 0; i < numElements; i++){
         printFunction(dest[i*size]); //make sure you index based on the type and not just a single byte
     }
 }
0
On

Its even much simpler, no multiplication needed, just pointer arithmetic:

void printArray(void *source, int numElements, int size, void (*printFunc)(void *)){
  while (numElements--) {
    printFunc(source);
    source=(char *)source+size; //C forbids void* math. source+=size fails on MSVC
  }
}