我认为隐藏结构定义会使代码更安全,因为您在编译器的帮助下强制执行,不能直接访问结构的任何成员。缺点是用户不能在堆栈上声明结构类型的变量,因为结构的大小是未知的,而有时候避免使用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()
的想法是能够在堆栈上声明结构但隐藏其定义。
答案 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
释放所有资源并释放它。
您提出的建议可以起作用,但容易出错,而不是一般解决方案。