1

This question is not a duplicate. I didn't find a solution in the question linked above

Using void* pointers, I wrote a function that prints out the elements of an array of any datatype. Basically, it accepts as parameters:

  1. a void* pointer (i.e. the array to print).
  2. the size of individual elements within the array.
  3. the array length.
  4. a pointer to a void function that accepts only a void* pointer as parameter which stores the address of the element of the array.
void printArray (void* pointer, int width, int numberOfElements, void (*functionPointer)(const void*))
{
    for (int i = 0; i < numberOfElements; i++)
    {
        functionPointer ((void*)(pointer + width*i));
    }
}

Then, I created different functions that print out a single variable; here, one of these:

void printInt (const void* v)
{
    int* myInt = (int*) v;
    printf ("%d ", *myInt);
}

What is left to do is to pass to printArray() the name of the print function I want to use, so that it can be generic. Below an example:

int tempArray [] = {0,1,2};
printArray (tempArray, sizeof (int), 3, printInt);

In order to print a 2d array, I've thought to put the "printArray" function in a for loop, considering every row of the matrix like a single array. To do so, I created this function, changing the void* pointer to a void** pointer and replacing the variable that stores the number of elements with the number of rows and cols of the matrix:

void printMatrix (void** pointer, int width, int rows, int cols, void (*functionPointer)(const void* v))
{
    for (int i = 0; i < rows; i++)
    {
        printArray ((pointer + i*width), width, cols, functionPointer);
        printf ("\n");
    }
}

Here, the main function:

#include <stdio.h>
#define ROWS 8
#define COLS 3

int main ()
{
    int matrix [ROWS][COLS] = {
            {0, 1, 2},
            {3, 4, 5},
            {6, 7, 8},
            {0, 3, 6},
            {1, 4, 7},
            {2, 5, 8},
            {0, 4, 8},
            {2, 4, 6}
    };

    printMatrix (matrix, sizeof (int), ROWS, COLS, printInt);

    return EXIT_SUCCESS;
}

The output:

0 1 2 
4 5 6 
8 0 3 
1 4 7 
5 8 0 
8 2 4 
57 8 2 
0 2 0 

I'm trying to understand where the problem is. How can I solve it?

EDIT

First of all, thank you everybody for answering. I solved the problem replacing the pointer + i*width in printArray ((pointer + i*width), width, cols, functionPointer); with pointer + i*cols, in this way:

for (int i = 0; i < rows; i++)
{
    printArray ((pointer + i*cols), width, cols, functionPointer);
    printf ("\n");
}

The printMatrix () function now works correctly.

Gennaro
  • 11
  • 3
  • In `pointer + i*width` remember that pointer arithmetic works in units of data elements, not bytes, and the pointer is `void*` so the size is unknown. How can your `printMatrix ` function know the size of each 2D array row without considering its type? – Weather Vane May 09 '19 at 18:59
  • A *bona fide* 2D array, such as you present in your test program, is an array of arrays. Therefore, you do not need a `printMatrix()` function, nor either additional functions for higher-dimensional arrays. The `printArray()` function you already have should suffice, provided that you pass it a suitable element-printing function (which will interpret the element to print as an array of the appropriate type and length). – John Bollinger May 09 '19 at 19:05
  • On the flip side, a bona fide 2D array, such as you present in your test program, is an array of arrays. Such an object is *not* a suitable argument to be matched with a parameter of type `void **`. – John Bollinger May 09 '19 at 19:09
  • I think you want `i*width*cols`, since you want to pass a pointer to the next line, not the next element.. – Aviv Goll May 09 '19 at 19:23
  • @JohnBollinger I've modified my function, now it works. Thank you for sharing that link but I don't find the solution of my problem in there. – Gennaro May 09 '19 at 20:08
  • @WeatherVane size is given by the parameter `int width`. When I call the `printMatrix()` function, I pass to it the `sizeof` operator. E.g., if my 2d array has type int, I will pass `sizeof (int)`, and so on.. – Gennaro May 09 '19 at 20:34
  • But the pointer arithmetic works with the *number of elements of that type*, not with the number of bytes. As in array indexing, `array[1]` refers to the second element, not (necessarily) the second byte. – Weather Vane May 09 '19 at 20:36
  • @WeatherVane no, it isn't. Suppose we have `int array [5];` with all the elements initialized: writing `array + 1` (that is equals to `array[1]`) means that we are adding the size of ONE int (which is 4 bytes, i.e. my `int width`) to the address location of `array`. In this way, `array` is pointing to the next contiguos memory block – Gennaro May 09 '19 at 21:21

0 Answers0