Either declaring the object visible in the interface to the module to an incomplete structure, or defining it to be a pointer to an incomplete structure are viable ways of information hiding. You should get an error regarding the incomplete type when code that does not have the definition of the structure elements tries to do somthing that requires knowing the size of that structure. (Declare a variable being most common). A common bug in this type of code is mistyping the name of the structure tag differently between its use in the typedef, and its use to declare the actual structure, this often results in errant errors about incomplete types in the implementation code.
Two sets of code follow. The files pitem.c pitem.h and pmain.c compile under gcc with -Wall with no warnings using the pointer approach. The files item.c item.h and main.c compile similarly using the incomplete structure approach.
Personally, I prefer the incomplete structure approach. The user of the interface knows they are dealing with a pointer in this approach. They have additional flexibility to initialize it to NULL as seen in main.c. Preference for this approach (as opposed to concealing the fact that the interface visible object is a pointer) is probably what tristopia's comment is referring to.
pitem.h
typedef struct ItemStruct *Item;
Item ItemGet();
pitem.c
#include "pitem.h"
#include <stdio.h>
#include <stdlib.h>
#define MAXSTRING 32
struct ItemStruct
{
char word[MAXSTRING];
int number;
};
Item ItemGet()
{
Item i;
i = (Item) malloc (sizeof(*i));
if (i == NULL)
{
fprintf ( stderr, "Error: insufficient memory for new element.\n");
return NULL;
}
return i;
}
pmain.c
#include "pitem.h"
int main(int argc , char **argv)
{
Item item;
(void) argc; /* not being used*/
(void) argv; /* not beign used*/
item = ItemGet();
(void)item; /* not being used */
return(0);
}
item.h
typedef struct ItemStruct Item;
Item *ItemGet();
item.c
#include "item.h"
#include <stdio.h>
#include <stdlib.h>
#define MAXSTRING 32
struct ItemStruct
{
char word[MAXSTRING];
int number;
};
Item *ItemGet()
{
Item *i;
i = (Item *) malloc (sizeof(*i));
if (i == NULL)
{
fprintf ( stderr, "Error: insufficient memory for new element.\n");
return NULL;
}
return i;
}
main.c
#include "item.h"
#include <stdlib.h>
int main(int argc , char **argv)
{
Item *pItem=NULL;
(void) argc; /* not being used*/
(void) argv; /* not beign used*/
pItem = ItemGet();
(void)pItem; /* not being used */
return(0);
}