user2419860
user2419860

Reputation: 101

c struct passing itself as an argument into a pointer function

I am trying to create a structure with nested functions, that passes the structure itself as an argument into the nested function for simplification of calling functions. The code will be run on a Pic 24f series mcu using the xc16 compiler. Also, I know the count function is redundant but I think it illustrates my point. For example:

Structure:

typedef struct
{
    uchar Fifo[UART1_RX_MAX_BUFFER_SIZE];
    uchar FifoIndex = 0;
    uchar FifoCount = 0;
    uchar FifoOverrunFlag = FALSE;
    uchar (*CountPointer);
    uchar (*PutPointer);
}Fifo;

Functions:

// Returns: The number of items in the Fifo
uchar FifoGetCount(Fifo *fifo)
{
    return fifo->FifoCount;
}

// Summary: Adds data to the end of the Fifo
// Parameters:  
//          data: Data to be added to the end of the Fifo
// Returns: True (1) if the data was successfully added
//      False (0) if the data was not successfully added
//          as a result of the Fifo being full
uchar FifoPut(Fifo *fifo, uchar data)
{
    if (fifo->FifoCount > FIFO_MAX_SIZE)
    {
        fifo->FifoOverrunFlag = TRUE;
        return FALSE;
    }
    uint putIndex = fifo->FifoGetPutIndex();
    fifo->Fifo[putIndex] = data;
    fifo->FifoCount++;
    return TRUE;
}

Main:

Fifo fifo1;

int main()
{
    fifo1.CountPointer = FifoGetCount(fifo1);
    fifo1.PutPointer = FifoPut(fifo1, uchar data);

    // Intended Usage
    uchar myCount = fifo1.FifoGetCount();
    uchar myData = 1;
    fifo1.FifoPut(myData);
}

Upvotes: 1

Views: 1155

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 754700

Note that uchar (*PutPointer); is just a funny way of writing uchar *PutPointer;. To create a function pointer, you'd have to write: uchar (*PutPointer)(…); where the should be replaced by a specification of the types of the arguments — a prototype.

Since you have a function uchar FifoPut(Fifo *fifo, uchar data), it seems likely that you should be writing:

typedef struct Fifo Fifo;

struct Fifo
{
    uchar Fifo[UART1_RX_MAX_BUFFER_SIZE];
    uchar FifoIndex = 0;
    uchar FifoCount = 0;
    uchar FifoOverrunFlag = FALSE;
    uchar (*CountPointer)(Fifo *fifo);
    uchar (*PutPointer)(Fifo *fifo, uchar data);
};

And then, in main(), you could write:

fifo1.CountPointer = FifoGetCount;
fifo1.PutPointer = FifoPut;

This assigns the function pointers FifoGetCount and FifiPut to the elements of the struct. The code you had assigned a uchar value generated by calling the function once to a uchar *. This should have been generating compiler warnings. If it was, you should have said so in your question. If it wasn't, you need turn on relevant compiler warnings, or get a better compiler.

You could then use the function as:

uchar myCount = fifo1.FifoGetCount(&fifo1);
uchar myData = 1;
fifo1.FifoPut(&fifo1, myData);

Note that you have to explicitly pass the address of the structure as the first argument to the functions; the C compiler is not going to do that for you by magic. If you want that done implicitly, the language you're looking for is called C++.

Upvotes: 1

Related Questions