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

时间:2015-12-15 22:14:56

标签: c memory-management struct alloca

我认为隐藏结构定义会使代码更安全,因为您在编译器的帮助下强制执行,不能直接访问结构的任何成员。缺点是用户不能在堆栈上声明结构类型的变量,因为结构的大小是未知的,而有时候避免使用malloc()是合乎需要的。这可以(部分成功)用alloca(3)解决,它存在于所有主要的libc实现中,尽管这个函数不符合POSIX。鉴于这种优点和缺点,这种设计通常可以认为是好的吗?

lib.h

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

lib.c

struct foo {
  int bar;
};

size_t foo_size = sizeof foo;

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

example.c

#include "lib.h"

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

UPD :更新了问题,明确指出使用alloca()的想法是能够在堆栈上声明结构但隐藏其定义。

2 个答案:

答案 0 :(得分:3)

是的,隐藏数据是一种好习惯。

替换为alloca(foo_size);是声明一个对齐的字符数组并执行指针转换。

指针转换不是完全可移植的。

如果大小需要是变量而不是编译时常量,则字符数组必须是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;

如果不需要/不提供VLA,请将大小声明为#define foo_N 100之类的常量,并且必须至少

答案 1 :(得分:2)

函数bar调用未定义的行为:foo指向的结构未初始化。

如果要隐藏结构详细信息,请提供一个foo_create()来分配一个并初始化它,并foo_finalize释放所有资源并释放它。

您提出的建议可以起作用,但容易出错,而不是一般解决方案。