-1

How can I have two different structs that refer to each other? One holds a pointer to the other and I also have a forward declaration:

struct json_array_t; 

struct json_array_entry_t {
    enum json_type type;                
    union {
        bool                boolean; 
        long long           integer; 
        double              floating; 
        char*               string; 
        struct json_array_t array; 
    }; 
}; 

struct json_array_t {
    struct json_array_entry_t* entries; 
    size_t len, cap;
};

I am getting these errors:

error: field ‘array’ has incomplete type
   27 |         struct json_array_t array;
  • 2
    To define an actual instance of a structure you need the full definition of the structure. To define a *pointer* to a structure you only need to know the structure tag. So do a forward declaration of the `json_array_entry_t` structure, and then change the order in which you define the structure. – Some programmer dude Jul 10 '20 at 15:46
  • @Someprogrammerdude thanks that worked –  Jul 10 '20 at 15:49
  • You say "To define a pointer to a structure you only need to know the structure tag". In my experience that is unnecessary. Just declare a pointer_to_some_type and the compiler will reserve space for a pointer and does type checking on assignment. Only once you want dereference the pointer and access its members, must the type fully be known. – Paul Ogilvie Jul 10 '20 at 16:04
  • It is highly recommended to change the names of the variables in the union of json_array_entry_t – Confidenc3 Jul 10 '20 at 16:45

3 Answers3

2

You must first define struct json_array_t and then struct json_array_entry_t.

When you now define in struct json_array_entry_t an occurrence of json_array_t it and all its members are fully known to the compiler.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
1

You can define json_array_entry_t before json_array_t since you will just use it as a pointer inside json_array_t

#include <stdio.h>
#include <stdbool.h>

// just an example
enum json_type {
  _BOOL, _INT, _DOUBLE, _STRING, _ARRAY
};

struct json_array_entry_t;

struct json_array_t {
  struct json_array_entry_t* entries; 
  size_t len, cap;
};

struct json_array_entry_t {
  enum json_type type;                
  union {
    bool                boolean; 
    long long           integer; 
    double              floating; 
    char*               string; 
    struct json_array_t array; 
  }; 
}; 

int main() {
  // some coding
  return 0;
}
Saadi Toumi Fouad
  • 2,779
  • 2
  • 5
  • 18
0

The compiler needs to know the exact size of struct json_array_t to determine how much memory it needs to allocate for the union member inside of the structure json_array_entry_t and with that how much memory it needs to allocate for an object of the structure json_array_entry_t in whole.

A simple forward declaration of struct json_array_t, as you did, is not sufficient in this case.

Place the definition of struct json_array_t

struct json_array_t {
    struct json_array_entry_t* entries; 
    size_t len, cap;
};

before the definition of struct json_array_entry_t. In this way the compiler knows the size of the structure json_array_t and you can also spare the forward declaration of it.

Since entries is only a pointer you don't need a forward-declaration for json_array_entry_t.


struct json_array_t {
    struct json_array_entry_t* entries; 
    size_t len, cap;
};

struct json_array_entry_t {
    enum json_type type;                
    union {
        bool                boolean; 
        long long           integer; 
        double              floating; 
        char*               string; 
        struct json_array_t array; 
    }; 
};