0

I have a header file (.h) with the following declaration.

typedef struct LinkedList LinkedList;

Afterwords in my LinkedList.c file I have the following

#include "LinkedList.h"
 typedef struct Node {...} Node;
 struct LinkedList {
Node *head;
int size;
 } LinkedList;

This set up is similar to the one I found over here with the difference being that I did not define the data members of the struct of LinkedList in my .h file (because I want to keep the Node stuff private). My understanding of header files is that any private structs are defined at implementation (i.e. in the .c file). Is this the proper way to do this? I have a initializeList function in my LinkedList.c file where I initalize size to 0 and head to NULL.

I then compiled this into a library file using

gcc -o LinkedList -c LinkedList.c

following the directions at here.

I then have a main.c file where I have the following

#include <stdio.h>
#include <stdlib.h>
#include "LinkedList.h"

int main()
{

LinkedList list1;
initializeList(list1);
for(int index = 1; index <= 5; index++)
{
   int input;
   printf("Enter num: ");
   scanf("%d", input);
   insertNthPosition(list1, input, index);
}

for(int index = 1; index <= 5; index++)
{
   printf("\n%d\n", getNthValue(list1, index));
}
return 1;

}

When I use gcc -o main main.c I get the following error

Storage size of 'list1' is not known

Community
  • 1
  • 1
user278039
  • 139
  • 6
  • Edited OP to clarify that I am using #include statement in my LinkedList.c file as is normally expected when doing a thing like this – user278039 May 27 '17 at 10:31
  • `LinkedList` is an opaque type for `main.c`. Variables cannot be declared as an opaque type, only as a *pointer* to an opaque type. – kaylum May 27 '17 at 10:31
  • Does that mean I would have to something `LinkedList *list1 = malloc(sizeof(struct LinkedList));` – user278039 May 27 '17 at 10:34
  • No, that can't be done for the same reason as your post - the size iof the opaque type is unknown. The library code should return `LinkedList *`. – kaylum May 27 '17 at 10:36

2 Answers2

0

The point is to keep Node declaration private: for that reason put in LinkedList.h this declaration:

typedef struct Node NodeType;
typedef struct LinkedList {
struct Node *head;
int size;
 } LinkedListType;

that would publicly declare LinkedListType, but not NodeType. Nevertheless this header states that NodeType (and struct Node) does exist.

Then put the actual declaration of Node type in the LinkedList.c file.

Now from any other translation unit you could access the LikedList instances, and access the NodeType pointer field too, but since you do not know the actual definition, you should never dereference it.

Note also that when you create main executable you miss the linking to the LinkedList object file you created with 'gcc -c' option before. I would suggest anyway to create a library and deliver that to clients of your linked list (and not object files).

Update: As pointed out in the comment, it is best practice to hide the implementation details of your linked list as well, not just of the type Node, as you mentioned in your question. Please create a linked list library that exposes functions that accepts and returns pointers to LinkedListType*. And let your clients deal with pointers to LinkedListType only. That is what is called an opaque pointer: you know it exists, but you cannot dereference it because you do not know its definition.

Luca Cappa
  • 1,925
  • 1
  • 13
  • 23
  • Why should `LinkedListType` be public at all? The OP is trying to hide even that part of it. So the answer can be improved if you explain how that can be achieved (in the same way as you have described how to do that for `NodeType`). – kaylum May 27 '17 at 11:17
  • I agree, i was guided by the sentence "I want to keep the Node stuff private" :) In the end, what the OP want is to use LinkedListType as an opaque pointer, never dereference it, but use it as a pointer everywhere, and the functions exported by the LinkedList library should accept/return pointers to that type :) – Luca Cappa May 27 '17 at 11:32
-1

I don't think that doing typedef in a header, and then defining the struct in .c file is a good idea.
Imagine that another file would like to use this struct. Then you need to re-type this struct all over again.
At the end, this is the whole point of header files. They are just copy-pastes.
So, if you need the struct only in one file, define the struct in this file. If you need this struct for multiple files, define the struct in the header and include it in both files.

Mk Km
  • 94
  • 6
  • This is totally wrong. The point of defining the struct only in .c file is so that the struct fields *cannot* be accessed outside that file. This is a well established way to hide the library implementation from client code. One example of this is the C standard `FILE` type. – kaylum May 27 '17 at 10:57