5

How do I declare, versus define a struct, such as for data shared between multiple files. I understand the idea when defining primitives. So, for example, I might have:

extern int myvalue;  /* in shared header file */

and

int myvalue = 5;   /* in data.c file */

But, how do I do the same thing for structs. For example, if I have the following type:

   typedef struct {
       size_t size;
       char * strings[];
   } STRLIST;

If I then use the statement:

STRLIST list;

This is both a declaration and definition. So, how do apply the same principle of using an extern?

Tyler Durden
  • 11,156
  • 9
  • 64
  • 126
  • If you want to assign a value of a stuct type in the same statement as declaring it, the syntax should be: `STRLIST list = {14, "stack overflow"}` – qleguennec Jul 05 '16 at 01:45
  • @qleguennec The statement I give allocates the structure I believe (although the string list is empty). – Tyler Durden Jul 05 '16 at 01:46
  • I don't get what you are trying to do, can you be clearer? How do you want to use the variable after declaring it? Should it be on the stack or the heap? – qleguennec Jul 05 '16 at 01:50
  • 1
    `STRLST* list;` definitely does *not* allocate the structure... it just declares a pointer to one. – Dmitri Jul 05 '16 at 01:53
  • @qleguennec I want to declare the struct in a shared header and define it in a c file. – Tyler Durden Jul 05 '16 at 01:59
  • To declare the variable, you'd write `extern STRLIST *list;` in the header where you define the structure type and the `typedef` — this is essentially the same as the `extern int myvalue;` in the header. Then in one source file, you'd define the structure pointer: `STRLIST *list = 0;`. If you link that file with the ones that reference the structure, all will be well. See also [How do I use `extern` to share variables between source files?](http://stackoverflow.com/questions/1433204/). – Jonathan Leffler Jul 05 '16 at 02:19
  • the code should be defining the `struct tagname { field names; };` in a header file. The code should be declaring (the implementation/instance of the struct) in a source file via `struct tagname instancename;`. Another source file can reference the struct declaration by `extern struct tagname instancename;` – user3629249 Jul 06 '16 at 16:20

3 Answers3

5

To declare an instance of a struct (or a pointer to one):

extern STRLIST* ptrList;
extern STRLIST list;

To define it:

STRLIST* ptrList;
STRLIST list;

To declare a struct type:

typedef struct STRLIST;

To define it:

typedef struct {
    size_t size;
    char * strings[];
} STRLIST;

Note that you can use a pointer to a struct with only a declaration, but you must have a definition to use the struct directly.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • How is STRLIST* list; an instance of a structure? – nicomp Jul 05 '16 at 02:03
  • I think the whole pointer thing is confusing the issue. I changed the example so that it is a plain struct, not a pointer. – Tyler Durden Jul 05 '16 at 02:54
  • @TylerDurden: The basics don't really change. `extern STRLIST list;` in the header declares the structure; `STRLIST list = { 0, 0 };` in a source file defines the structure (initialization optional but recommended). —— _skip this_ —— With pointers, there's an extra stunt you can pull — not providing the structure definition: `typedef struct STRLIST STRLIST;` and then `extern STRLIST *list;` and `STRLIST *list = 0;`, using an opaque type. You'd not be able to refer to the elements of the structure except in the code that defines the structure type. But maybe you should skip that for now. – Jonathan Leffler Jul 05 '16 at 02:59
3

Every name in C, before it is used, has to be declared. To declare is (just) to explain what type the name describes. This is information for the compiler how to treat the object of this name.

Definition, on the other hand, instructs the compiler to reserve memory for the object. A definition is always also a declaration.

In your case, the statement:

STRLIST* list;

is indeed a definition but it is a definition of a pointer to your (earlier declared) struct. It declares the name 'list' and it also reserves memory for the address that may point to an object of your struct after it is defined. So it does not in fact define the actual struct. It does not create an object described by your structure — it does not reserve/allocate memory for such an object.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Walt
  • 76
  • 4
1

Just a small clarification to dbush's answer:

From the latest C standard (Feb 2020):

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2494.pdf

6.7.2.1 Structure and union specifiers (p1)

Syntax

1 struct-or-union-specifier:

struct-or-union attribute-specifier-sequenceopt identifieropt { member-declaration-list }

In conclusion, the part:

struct STRLIST{
    size_t size;
    char * strings[];
};

Is your struct's declaration.

Adding the typedef, defines the type STRLIST:

typedef struct {
    size_t size;
    char * strings[];
} STRLIST;

And this is your definition:

STRLIST list;

Rule of thumb: a definition provides memory to the instance. a declaration doesn't.

Inbal2l
  • 31
  • 1
  • 4