隐藏结构成员 [英] Hiding Struct Members

查看:51
本文介绍了隐藏结构成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道之前可能有人问过这个问题,但我想采取我的方法并获得意见或可能的更好方法.我有三个文件 ah acmain.c 关于结构的函数原型将在 ah 中实现将在 ac 中并从 main.c 调用结构将很简单它看起来像这样

I know this question might have been asked before but I wanted to take my approach at it and get an opinion or possibly a better way to do it. I have three files a.h a.c and main.c Prototypes of functions regarding the struct will be in a.h while implementation will be in a.c and called from main.c the structure will be simple it can just look like this

struct ctx{
    int x;
};

我希望 a.c 能够操作结构体的内容,但防止 main 知道里面的内容.所以我想把结构定义放在 ac 而不是 ah 并把 struct ctx; 作为原型放在 ah>这可以工作,但是 ctx 不能再在 main.c 的堆栈上分配,因为编译器不知道要分配的大小.所以这就引出了我的第一个问题:有没有办法在不知道结构定义的情况下将结构分配到堆栈本地.

I want a.c to be able to manipulate the contents of the struct but prevent main from having any idea of what's inside. So I figured placing the struct definition inside a.c instead of a.h and placing just struct ctx; as a prototype in a.h And this could work, however ctx can no longer be allocated on the stack in main.c because the compiler doesn't know the size to allocate. So this leads me to my first question: Is there a way to allocate the structure local to the stack without knowing the definition of the structure.

所以我假设如果它在堆栈上是不可能的,那么也许我可以将它传递到堆上,而不是通过创建一个简单的 init 函数来返回一个指针.这确实有效,但会不会使流程过于复杂?

So I assumed if it wasn't possible on the stack then maybe I could just pass it on the heap instead by creating a simple init function that returns a pointer. And that does work but would it be over complicating the process?

a.h

#ifndef a_h
#define a_h

#include <stdio.h>
#include <stdlib.h>
struct ctx;
int incctx(struct ctx* c);
struct ctx* initctx(void);
void destroyctx(struct ctx* c);
#endif /* a_h */

a.c

#include "a.h"
struct ctx{
    int x;
};
int incctx(struct ctx* c){
    return ++c->x;
}
struct ctx* initctx(){
    struct ctx* c =  malloc(sizeof(struct ctx));
    c->x = 0;
    return c;
}
void destroyctx(struct ctx* c){
    free(c);
}

main.c

#include "a.h"

int main(){
    struct ctx* c = initctx();
    printf("%d\n",incctx(c));
    printf("%d\n",incctx(c));
    printf("%d\n",incctx(c));
    destroyctx(c);
    return 0;
}

这种设计解决了一些缺点的问题.1:如果我想让部分结构可见而不是整个事物怎么办?2:如果我想让结构定义对其他文件可用,比如 b.hb.c 我是否必须重新定义结构?你们有没有更干净的设计?我知道有些人说你可以在结构中放置一个 void* 而不是特定类型,然后将它们标记为任意名称,但我认为这不是一个可行的解决方案.

This design kind of solves the problem with a few drawbacks. 1: What if I wanted to make parts of the structure visible but not the entire thing? 2: If I wanted the structure definition to be available to other files say b.h and b.c would I have to redefined the structure? Do any of you have a cleaner design? I know some people say you can just place a void* in the structure instead of specific types and just label them arbitrary names but I don't see that as a viable solution.

推荐答案

对于可见性问题,您可以以类似继承的方式使用两个结构.

For the visibility problem you can use two structure in an inheritance-like way.

首先,您拥有在头文件中定义的公共结构以及您的 API 处理指向的指针:

First you have the public structure that you define in the header file and which your API handles pointers to:

struct ctx
{
    // Public data
};

然后在源文件中创建一个私有结构,其中公共结构是第一个成员:

Then in the source file you create a private structure, where the public structure is the first member:

struct private_ctx
{
    struct ctx ctx;  // The public part of the structure

    // Followed by private data
};

在 API 内部,您使用 private_ctx 结构,而使用您的 API 的代码将仅使用公共 ctx 结构.

Internally inside the API you use the private_ctx structure, while the code using your API will only use the public ctx structure.

这样的嵌套结构与继承类似,private_ctx结构是一个 ctx结构.您可以创建一个 private_ctx 结构并返回一个指向它的指针,该指针适当地转换为 ctx 结构.

Nested structures like this works similarly to inheritance, the private_ctx structure is a ctx structure. You can create a private_ctx structure and return a pointer to it suitably casted to a ctx structure.

以下是有关如何创建结构的示例:

Here's an example on how to create the structure:

struct ctx *create_struct(void)
{
    // Allocate the private structure, which contains the public structure
    struct private_ctx *data = = malloc(sizeof *data);

    // Return the public part of the structure
    return (struct ctx *) data;
}

通过反向转换同样容易使用私有数据:

Using the private data is equally easy with a reverse cast:

void use_data(struct ctx *data)
{
    struct private_ctx *private_data = (struct private_ctx *) data;

    // Here the private data can be used...
}

这篇关于隐藏结构成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆