如何在C中隐藏某些结构字段?

Woo*_*iae 18 c typedef

我正在尝试实现一个struct person,我需要隐藏一些字段或使其保持不变。 创建私有字段的技巧。

标头:

#pragma once

#define NAME_MAX_LEN 20

typedef struct _person {
    float wage;
    int groupid;
} Person;

const char const *getName (Person *p);
int getId (Person *p);

/// OTHER FUNCTIONS
Run Code Online (Sandbox Code Playgroud)

资源

#include "person.h"


struct _person
{
    int id;

    float wage;
    int groupid;

    char name[NAME_MAX_LEN];
};

/// FUNCTIONS
Run Code Online (Sandbox Code Playgroud)

海湾合作委员会说 person.c:7:8: error: redefinition a 'struct _person' struct _person

我可以将其写在标题中,但是在此之后,就不能使用结构的字段。

typedef struct _person Person;
Run Code Online (Sandbox Code Playgroud)

dbu*_*ush 24

一个结构不能有多个冲突的定义。因此,您无法创建隐藏某些字段的结构。

但是,您可以做什么,但声明该结构存在于标头中而不定义它。然后,调用方被限制为仅使用指向该结构的指针,并在实现中使用函数对其进行修改。

例如,您可以按以下方式定义标题:

typedef struct _person Person;

Person *init(const char *name, int id, float wage, int groupid);

const char *getName (const Person *p);
int getId (const Person *p);
float getWage (const Person *p);
int getGroupid (const Person *p);
Run Code Online (Sandbox Code Playgroud)

您的实现将包含:

#include "person.h"

struct _person
{
    int id;

    float wage;
    int groupid;

    char name[NAME_MAX_LEN];
};

Person *init(const char *name, int id, float wage, int groupid)
{
    Person *p = malloc(sizeof *p);
    strcpy(p->name, name);
    p->id = id;
    p->wage= wage;
    p->groupid= groupid;
    return p;
}

...
Run Code Online (Sandbox Code Playgroud)


Joh*_*ger 17

C没有隐藏结构类型的单个成员的机制。但是,通过仅根据指向这种类型的指针进行操作而不提供定义,可以使整个类型不透明。然后,用户将不得不使用您提供的功能以任何方式操纵实例。这是有时要做的事情。

在某种程度上,您可以实现类似于您在隐藏上下文中描述的内容。例如,考虑一下:

头文件

typedef struct _person {
    float wage;
    int groupid;
} Person;
Run Code Online (Sandbox Code Playgroud)

实施

struct _person_real {
    Person person;  // must be first, and is a structure, not a pointer.
    int id;
    char name[NAME_MAX_LEN];
};
Run Code Online (Sandbox Code Playgroud)

现在您可以执行以下操作:

Person *create_person(char name[]) {
    struct _person_real *pr = malloc(sizeof(*pr));

    if (pr) {
        pr->person.wage = DEFAULT_WAGE;
        pr->person.groupid = DEFAULT_GROUPID;
        pr->id = generate_id();
        strncpy(pr->name, name, sizeof(pr->name));
        pr->name[sizeof(pr->name) - 1] = '\0';

        return &pr->person;  // <-- NOTE WELL
    } else {
        return NULL;
    }
}
Run Code Online (Sandbox Code Playgroud)

指向结构的第一个成员的指针也总是也指向整个结构,因此,如果客户端将从该函数获得的指针传递回给您,则可以

struct _person_real *pr = (struct _person_real *) Person_pointer;
Run Code Online (Sandbox Code Playgroud)

并从更大的范围对成员进行工作。

但是,请注意,这样的方案存在风险。没有什么可以阻止用户在Person 没有较大上下文的情况下创建,并将指向它的指针传递给期望存在上下文对象的函数。还有其他问题。

总体而言,C API通常采用不透明的结构方法,或者只是仔细地记录允许客户使用其访问的数据做什么,甚至只是记录一切如何工作,以便用户可以做出自己的选择。这些方法,尤其是后者,与整体C方法和习惯用法完全吻合-C不能握住您的手,或保护您免受伤害。它信任您知道您在做什么,并且仅执行您打算做的事情。

  • 最好还是使用完全不透明的指针,这样用户就不会尝试分配自己的`Person`。 (4认同)