2

Description of the problem

I am wondering about the "right way" to define structs in C to use them by other source files. Think about the following struct

struct f3{
  double x;
  double y;
  double z;
};

Question

Should typedefs and structs be declare in a header file or source file? If in a header file, what should be included in that header file in order to comply with the C software engineering techniques?

What I have done so far:

I could place it in types.h and then use struct f3 in other source files (#include types.h) or it could be placed in the source file type.c.

Manolete
  • 3,431
  • 7
  • 54
  • 92
  • 2
    Put declarations in the header file. `struct` is a declaration. – Ed Heal Jun 05 '16 at 21:11
  • 1
    @EdHeal Every definition is also a declaration. `struct f3 { ... }` is a definition. – melpomene Jun 05 '16 at 21:17
  • @melpomene: It is a `struct` _specifier_ actually. – too honest for this site Jun 05 '16 at 21:22
  • 1
    Also look up 'opaque types' or 'opaque pointers'. Sensible questions on SO include: [What defines an opaque type in C?](https://stackoverflow.com/questions/2301454/), [What is an opaque pointer in C?](https://stackoverflow.com/questions/7553750/), [Why should we typedef a struct so often in C?](https://stackoverflow.com/questions/252780/), [Repeated typedefs — invalid in C but valid in C++?](https://stackoverflow.com/questions/8594954/repeated-typedefs-invalid-in-c-but-valid-in-c/), [Best place to define a struct for a library?](https://stackoverflow.com/questions/16781586/) – Jonathan Leffler Jun 05 '16 at 22:35
  • in general, this question wants an opinion based answer and the best answer would depend of the number of files, involved, etc. questions requiring an opinion for an answer are off-topic on stackexchange.com – user3629249 Jun 06 '16 at 03:03

2 Answers2

6

If you need to use the type in more than one source file, put it in a header (and have each source file include it).

If a type is internal to a source file, put it in there (and no one else has to know about it).

C also provides a third way (which gives you abstract types), which is called "incomplete types". To do this, you would put struct f3 { ... }; in your source file and struct f3; in your header file. This lets other files know that the type exists and they can use pointers to struct f3, but they can't see the internals of struct f3 or access its members.

melpomene
  • 84,125
  • 8
  • 85
  • 148
4

This depends on how much information you want to share with the outside world.

Assuming, that struct is to be shared between multiple translation units, the most straighforward way is to put struct type declaration into a header file. It is called as complete struct declaration:

struct f3{
  double x;
  double y;
  double z;
};

The second way is to hide the members by the incomplete struct declaration, sometimes refferred to as forward declaration or an opaque pointer. This way you can hide the details of how members are placed inside.

header.h

struct f3;

source.c

#include "header.h"

struct f3{
  double x;
  double y;
  double z;
};

This form requires, that any function from the public interface must only contain parameters, that are pointers to that struct as well as they can return such struct only by a pointer. In other words, you cannot refer to the struct directly, only by a pointer. For example:

double area(struct f3* point);
struct f3* makePoint(int x, int y, int z);
Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
  • 1
    The question is not how much information you want to share with the outside world but rather how much information is needed by the outside world. If `struct f3` is going to be used nowhere but `source.c` then there's no reason to put it somewhere else. The only reason to create header files at all is to share them with multiple source files. – Carey Gregory Jun 05 '16 at 21:34
  • 1
    @CareyGregory: OP's specified in question directly, that `to use them by other source files`, so I take that for granted. But of course you are right, the situation simplfies greatly, if struct does not need to be visible outside of an single translation unit. – Grzegorz Szpetkowski Jun 05 '16 at 21:40