admin管理员组文章数量:1122832
#ifndef HANDLE_H
#define HANDLE_H
struct List;
typedef struct List* HANDLE;
struct Person;
typedef struct Person Person_t;
HANDLE list_create(void);
void list_destroy(HANDLE);
void list_push_front(HANDLE, const Person_t*);
void list_pop_front(HANDLE);
#endif // HANDLE_H
Question: Are the forward declarations (List
and Person
) needed, and is it a good practice to forward declare them?
#ifndef HANDLE_H
#define HANDLE_H
struct List;
typedef struct List* HANDLE;
struct Person;
typedef struct Person Person_t;
HANDLE list_create(void);
void list_destroy(HANDLE);
void list_push_front(HANDLE, const Person_t*);
void list_pop_front(HANDLE);
#endif // HANDLE_H
Question: Are the forward declarations (List
and Person
) needed, and is it a good practice to forward declare them?
3 Answers
Reset to default 2Forward declarations are only needed when the struct definition isn't already visible earlier inside the same translation unit or otherwise you wouldn't be able to use the struct. Forward declarations can be done with or without typedef
. Meaning that the struct Person;
etc parts are redundant here.
Regarding best practices:
It is often good practice to hide implementation details of a struct to a caller which should not access it directly. That is known as "opaque type" and is one way to achieve private encapsulation. See How to do private encapsulation in C?
It is widely considered as very bad practice to hide pointers behind
typedef
. Even in the case of opaque types.An example of one of the most infamous code bases out there is the Windows API, which uses something called
HANDLE
very similar to what you have here. One of many problems with this is that the programmer doesn't realize that they are dealing with a pointer and therefore add one more level of needless indirection, leading to slower code which is harder to read. Another problem is that they might think they are performing a hard copy of the whole object when assigning one HANDLE to another. Just don't do this.
The separate line declaring each struct type isn't strictly required. This:
typedef struct List* HANDLE;
Besides defining the type HANDLE
, also declares struct List
, and the same for the other typedef.
So your header can safely contain the following:
#ifndef HANDLE_H
#define HANDLE_H
typedef struct List* HANDLE;
typedef struct Person Person_t;
HANDLE list_create(void);
void list_destroy(HANDLE);
void list_push_front(HANDLE, const Person_t*);
void list_pop_front(HANDLE);
#endif // HANDLE_H
A forward declaration for a structure is not required before a typedef declaration for that structure. So instead of that
struct List;
typedef struct List* HANDLE;
struct Person;
typedef struct Person Person_t;
you may just write
typedef struct List* HANDLE;
typedef struct Person Person_t;
Pay attention to that if you are going to use a typedef declaration for an enumeration then the enumeration shall be defined either before the typedef or inside the typedef.
本文标签: cAre forward declarations needed when the typedef declaration is doneStack Overflow
版权声明:本文标题:c - Are forward declarations needed when the typedef declaration is done? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736310297a1934326.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
struct List;
orstruct Person;
in the code shown because these structure tags are introduced bytypedef struct List *HANDLE;
andtypedef struct Person Person_t;
, respectively. – Eric Postpischil Commented Nov 21, 2024 at 14:07typedef struct Person Person_t;
(one line, not two). Similarly with the list structure. Normally, the structure tag and the typedef name should be related, as withPerson
andPerson_t
. Emulating C++, you can use the tag name as the typedef name (typedef struct List List;
) — C++ achieves the same effect automnatically. – Jonathan Leffler Commented Nov 21, 2024 at 15:51