9

So, out of the blue, the compiler decides to spit this in face: "field customer has incomplete type".

Here's the relevant snippets of code:

customer.c

#include <stdlib.h>
#include <string.h>

#include "customer.h"

struct CustomerStruct;
typedef struct CustomerStruct
{
    char id[8];
    char name[30];
    char surname[30];
    char address[100];
} Customer ;

/* Functions that deal with this struct here */

customer.h

A header file for customer.h

#include <stdlib.h>
#include <string.h>

#ifndef CUSTOMER_H
#define CUSTOMER_H

    typedef struct CustomerStruct Customer;

    /* Function prototypes here */

#endif

This is where my problem is:

customer_list.c

#include <stdlib.h>
#include <string.h>

#include "customer.h"
#include "customer_list.h"

#include "..\utils\utils.h"


struct CustomerNodeStruct;
typedef struct CustomerNodeStruct
{
    Customer customer; /* Error Here*/
    struct CustomerNodeStruct *next;
}CustomerNode;



struct CustomerListStruct;
typedef struct CustomerListStruct
{
    CustomerNode *first;
    CustomerNode *last;
}CustomerList;

/* Functions that deal with the CustomerList struct here */

This source file has a header file, customer_list.h ,but I don't think its relevant.

My Problem

In customer_list.c, at the line with the comment /* Error Here */, the compiler complains about field customer has incomplete type.

I've been googling this problem all day, and now im at the point of pulling out my eyeballs and blending them with strawberries.

What is the source of this error ?

Thanks in advance :)

[P.S. if I forgot to mention something, let me know. Its been a stressful day for me, as you might tell ]

Zyyk Savvins
  • 453
  • 2
  • 8
  • 13
  • 1
    The struct definition itself would have to be in the header, not just the typedef. – James McLaughlin Nov 29 '12 at 20:53
  • The compiler needs to know the `struct`, because it needs to know the size of every data. – Basile Starynkevitch Nov 29 '12 at 20:54
  • The first thing that jumps out at me is the `"..\utils\utils.h"`, but I doubt that causes the error. Still, `tils` is not a hex number. – Mr Lister Nov 29 '12 at 20:55
  • Let me guess... If you change the order of includes `customer.h` and `customer_list.h` everything starts to work. You should define your struct before you are using it! – Kylo Nov 29 '12 at 20:56
  • thats just a header for a source file i wrote, with common functions that I use throughout my project. Removes repetitive code :) – Zyyk Savvins Nov 29 '12 at 20:57

4 Answers4

14

Move the struct declaration to the header:

customer.h
typedef struct CustomerStruct
{
...
}
cnicutar
  • 164,886
  • 23
  • 329
  • 361
  • so wait ... I declare the typedef and struct in the header file. But what does that leave in the source file ? – Zyyk Savvins Nov 29 '12 at 20:54
  • @ZyykSavvins The problem is that the compiler doesn't know what the struct looks like. – cnicutar Nov 29 '12 at 20:55
  • @ZyykSavvins Usually functions that consume the struct, e.g. `print_customer(Customer *cust)`. If you require no functions, then you need not define a .c file, you can just have the header file with no accompanying .c file. – user295691 Nov 29 '12 at 20:57
  • Thanks! I actually do have some functions. Only now the struct is declared in the header. Thanks again :) Problem solved – Zyyk Savvins Nov 29 '12 at 21:01
8

In C, the compiler needs to be able to figure out the size of any object that is referenced directly. The only way that the sizeof(CustomerNode) can be computed is for the definition of Customer to be available to the compiler when it is building customer_list.c.

The solution is to move the definition of the struct from customer.c to customer.h.

Brighter side
  • 382
  • 2
  • 14
user295691
  • 6,728
  • 1
  • 22
  • 33
  • -.- something told me it was something simple. Thanks! It worked. So just to be clear, I define and declare my structs and typedefs in my header files, and then include the header file in its matching source file ? – Zyyk Savvins Nov 29 '12 at 20:58
  • You can include the header file in any .c or .h file that requires the structs and typedefs that you have defined. In addition to structs and typedefs, you would also put any prototypes for functions related to the functionality in the header file. In the matching .c file, you would put the implementation of the functions. If there are no functions to implement, then usually you would omit the .c file entirely. – user295691 Nov 29 '12 at 23:24
3

What you have is a forward declaration of Customer structure that you are trying to instantiate. This is not really allowed because compiler has no idea about the structure layout unless it sees it definition. So what you have to do is move your definition from the source file into a header.

3

It seems that something like

typedef struct foo bar;

won't work without the definition in the header. But something like

typedef struct foo *baz;

will work, as long as you don't need to use baz->xxx in the header.

pajaja
  • 2,078
  • 4
  • 21
  • 31