1

I'm getting the dereferencing pointer to incomplete type error when I try to run the following code. I've checked several other questions about this error and from what I can tell it's not due to a missing or extra struct keyword and I believe the pointer type is correct but I could be mistaken.

There might be other issues with the code as I'm just learning C, I'm happy to try and figure them out for myself I just can't seem to track down the issue with the incomplete type error.

Development/C/AI/test/src/test.c: In function ‘compare’:
Development/C/AI/test/src/test.c:10:19: error: dereferencing pointer to incomplete type ‘lrgraph_node {aka struct lrgraph_node}’
  if ( strcmp(other->dataType, current->dataType == 0) ) {

test.c

#include "lrGraph.h"
#include <string.h>

int data = 1;
char *dataType = "int";
lrgraph_edge *connected[] = {};
unsigned numEdges = 0;

int compare( lrgraph_node *other, lrgraph_node *current ) {
    if ( strcmp(other->dataType, current->dataType == 0) ) {
        return (int)other->data - (int)current->data;
    }
    return -1;
}

int main() {
    lrgraph_node *nodeA = lrgraph_createNode((void*)&data, dataType, &compare, connected, numEdges);
    lrgraph_printVersion();
}

lrGraph.c

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

struct lrgraph_edge {
    float weight;
    lrgraph_node *nodeA;
    lrgraph_node *nodeB;
};

struct lrgraph_node {
    //data can be of any type
    void *data;
    //string to see if this node can be compared to another node based on data type
    char *dataType;
    int numEdges;
    //comparator function which compares another node to this node
    int (*compare)(lrgraph_node *other, lrgraph_node *current);
    //array of connected edges
    lrgraph_edge *connected[];
};

void lrgraph_printVersion() {
    fprintf(stdout, "\nlrgraph version 0.01b\n");
}


lrgraph_node* lrgraph_createNode(void *data, char *dataType, int (*compare)(lrgraph_node* other, lrgraph_node* current), lrgraph_edge *connected[], unsigned numEdges) {
    //allocate enough memory for the struct plus each pointer in the array of edges - https://stackoverflow.com/questions/32311269/can-we-have-a-struct-element-of-type-variable-length-array
    lrgraph_node *node = malloc(sizeof(lrgraph_node) + numEdges * sizeof(lrgraph_edge));
    if (NULL != node) {
        node->data = data;
        node->dataType = strdup(dataType);
        node->compare = compare;
        node->numEdges = numEdges;
        //initialize each edge in the array
        for( unsigned i=0; i < numEdges; i++) {
            node->connected[i] = connected[i];
        }
    }
    return node;
}

lrGraph.h

#ifndef LRGRAPH_H
#define LRGRAPH_H

typedef struct lrgraph_node lrgraph_node;

typedef struct lrgraph_edge lrgraph_edge;

lrgraph_node* lrgraph_createNode(void *data, char *dataType, int (*compare)(lrgraph_node *other, lrgraph_node *current), lrgraph_edge *connected[], unsigned numEdges);

void lrgraph_printVersion();

#endif /*LRGRAPH_H*/
LiamRyan
  • 1,892
  • 4
  • 32
  • 61
  • 1
    There is no definition of `lgraph_node`. Is it defined anywhere? – Iharob Al Asimi Aug 28 '17 at 17:13
  • lrGraph.h and lrGraph.c, unless I've defined incorrectly and that's the problem – LiamRyan Aug 28 '17 at 17:14
  • 2
    You placed your type definitions in `lrGraph.c`. The types are complete only in `lrGraph.c`. In all other `.c` files they are incomplete. Why did you place your type definitions in `lrGraph.c`? If you want your types to be complete in multiple `.c` files, then the definitions must be readily in all these `.c` files, i.e. they should reside in the header file. – AnT stands with Russia Aug 28 '17 at 17:14
  • Your `compare` needs to know the full and exact definition of `lrgraph_node`, which it does not have (the header only declares the typedef, and not the actual `struct`). In other words, the error is exactly correct that you have an incomplete type with regards to that part of the code. – crashmstr Aug 28 '17 at 17:18
  • 1
    Are you sure you didn't mean `strcmp(other->dataType, current->dataType) == 0` ? – vgru Aug 28 '17 at 17:59
  • yes I did, thanks. As I said the code may have issues in other areas I was just stuck on the struct problem – LiamRyan Aug 28 '17 at 18:05

1 Answers1

5

"Incomplete type" means the compiler sees you're trying to use a struct type but there is no definition for that struct.

This is fine if you're only using pointers to structs (and is in fact how abstract data types are implemented in C), but if you want to dereference such a pointer, a struct definition must be visible.

In test.c only the contents of lrGraph.h are visible (i.e. typedef struct lrgraph_node lrgraph_node;), but the actual struct lrgraph_node { ... }; definition exists only in lrGraph.c.

Possible solution: Move the struct lrgraph_node { ... } definition into the header. (Alternatively, put the definition of compare into lrGraph.c).

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • Thanks this answers why the issue exists but is there a way in C to hide the implementation of a struct while allowing a user to pass a function for that struct to use? I was trying to do something like qsort here where a user provides a comparator when creating a node – LiamRyan Aug 28 '17 at 17:25
  • 1
    @SMC If you create functions in `lrGraph.c` which return the `data` and `dataType` of a node pointer (and declare them in `lrGraph.h`), you can use those functions in `test.c`. You might also want graph traversal functions, and functions for anything else you want others to be able to do. – Daniel H Aug 28 '17 at 17:34