Search code examples
cpointersfunction-pointerspointer-to-member

Pointer Functions in C: initialization of foo from incompatible pointer type


I'm working with C, and not allowed to use C++. Currently, I'm trying to implement some level of OOP in C. I'm currently working on trying to implement polymorphism and inheritance.

I've spent the majority of the day reading up on how my goals are possible through the use of function pointers. I am attempting to print the members variables of both structs as seen here:

RecordObject.h

typedef struct SuperRecordObject 
{
    char *Id;
    char *date;
    char *cases;
    char *deaths;
    void (*ptrPrintRecord)(char *id, char *date, char *cases, char *deaths, char *names_fr, char *names_en);  
} SuperRecord;

typedef struct ChildRecordObject
{
    SuperRecord super;
    char *names_fr;
    char *names_en;
} ChildRecord;

I have defined the function ptrPrintRecord in this file:

RecordObject.c

#include <stdio.h>
#include "RecordObject.h"
void ptrPrintRecord(char *id, char *date, char *cases, char *deaths, char *names_fr, char *names_en)
{
    //char *record;
    printf("     %s |   %s |            %s | %s |   %s |  %s\n", id, date, cases, deaths, names_fr, names_en);
    //return record;   
}

And I try to use the function in this file, as such:

DataLayer.c

#include <stdio.h>
#include <string.h>
#include "RecordObject.h"
/* more code here */

void(*fun_ptr)(char*,char*,char*,char*,char*,char*) = &record.super.ptrPrintRecord; //
(*fun_ptr)(record.super.Id, record.super.date, record.super.cases, record.super.deaths, record.names_fr, record.names_en);

/* more code here */

However, when I compile (using GCC), I get this warning which causes a crash.

warning: initialization of 'void (*)(char *, char *, char *, char *, char *, char *)' from incompatible pointer type 'void (**)(char *, char *, char *, char *, char *, char *)' [-Wincompatible-pointer-types]
   62 |        void(*fun_ptr)(char*,char*,char*,char*,char*,char*) = &record.super.ptrPrintRecord;

I've ran some other pointer functions in other files to mess around and test it, and the only thing I can think of as to what's going on here is it's maybe got something to do with how strings work in C?


Solution

  • You have an extraneous & in your attempted function pointer assignment. The ptrPrintRecord member of your structure is already a function pointer of the correct type, so you don't need the & - which would give the address of that pointer.

    Just use:

    void(*fun_ptr)(char*, char*, char*, char*, char*, char*) = record.super.ptrPrintRecord; // No &
    

    As a side note, your use of ptrPrintRecord as that member (function pointer) and also as the name of an actual function (with the same 'signature') is likely to cause some issues, further down the road.


    Furthermore, you need to actually initialize that member (pointer) to a valid function address before copying it to something you then call (as also with the other members of the structure). Here's a small main (using your other code) that works:

    int main()
    {
        ChildRecord record;
        record.super.ptrPrintRecord = ptrPrintRecord; // See my note about the name clash!
        record.super.Id = "ID";
        record.super.date = "today";
        record.super.cases = "cases";
        record.super.deaths = "deaths";
        void(*fun_ptr)(char*, char*, char*, char*, char*, char*) = record.super.ptrPrintRecord; //
        // To call the pointed-to function, we can just use the pointer name:
        fun_ptr(record.super.Id, record.super.date, record.super.cases, record.super.deaths, record.names_fr, record.names_en);
        return 0;
    }