简体   繁体   English

在 C 中隐藏结构定义是一个好习惯吗?

[英]Is it a good practice to hide structure definition in C?

In my opinion, hiding the definition of a structure in C generally makes code safer, as you enforce—with the help of the compiler—that no member of the structure can be accessed directly.在我看来,在 C 中隐藏结构的定义通常会使代码更安全,因为您在编译器的帮助下强制要求不能直接访问结构的任何成员。

However, it has a downside in that a user of the structure cannot declare variables of its type to be put on the stack, because the size of the structure becomes unavailable this way (and, therefore, the user has to resort to allocating on the heap via malloc() even when it is undesirable).然而,它有一个缺点,即结构的用户不能声明其类型的变量以放入堆栈,因为结构的大小以这种方式变得不可用(因此,用户不得不求助于分配堆通过malloc()即使是不受欢迎的)。

This can be (partially) solved via the alloca(3) function that is present in all major libc implementations, even though it does not conform to POSIX .这可以(部分)通过alloca(3)函数解决,该函数存在于所有主要的 libc 实现中,即使它不符合 POSIX

Keeping these pros and cons in mind, can such design be considered good in general?牢记这些优点和缺点,这样的设计总体上可以被认为是好的吗?

In lib.h :lib.h

struct foo;
extern size_t foo_size;
int foo_get_bar(struct foo *);

In lib.c :lib.c

struct foo {
  int bar;
};

size_t foo_size = sizeof foo;

int foo_get_bar(struct foo *foo)
{
  return foo->bar;
}

In example.c :example.c

#include "lib.h"

int bar(void)
{
  struct foo *foo = alloca(foo_size);
  foo_init(foo);
  return foo_get_bar(foo);
}

Yes, it is a good practice to hide data.是的,隐藏数据是一个好习惯。

As an alternate to the alloca(foo_size);作为alloca(foo_size);的替代方法alloca(foo_size); pattern, one can declare an aligned character array and perform a pointer conversion.模式,可以声明一个对齐的字符数组并执行指针转换。 The pointer conversion is not fully portable, though.但是,指针转换并不是完全可移植的。 The character array needs to be a VLA, if the size is defined by a variable and not a compile-time constant:如果大小由变量而不是编译时常量定义,则字符数组需要是 VLA:

extern size_t size;

struct sfoo;

#include <stddef.h>

int main(void) {
  unsigned char _Alignas (max_align_t) cptr[size];
  // or unsigned char _Alignas (_Complex  long double) cptr[size];  // some widest type
  struct sfoo *sfooptr = (struct sfoo *) cptr;
  ...

If VLAs are not desired or available, declare the size as a constant ( #define foo_N 100 ) that is guaranteed to be at least as much as needed.如果不需要或不可用 VLA,请将大小声明为常量 ( #define foo_N 100 ),保证至少与需要一样多。

Function bar invokes undefined behavior: the structure pointed to by foo is uninitialized.函数bar调用未定义的行为: foo指向的结构未初始化。

If you are going to hide the structure details, provide a foo_create() that allocates one and initializes it and foo_finalize that releases any resources and frees it.如果你打算隐藏结构细节,提供一个foo_create()分配一个并初始化它, foo_finalize释放任何资源并释放它。

What you are proposing could be made to work, but is error prone and is not a general solution.您提出的建议可以起作用,但容易出错并且不是通用解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM