简体   繁体   English

访问另一个 c 文件中定义的结构?

[英]Accessing a struct defined in another c file?

I am trying to access a struct defined in one c file from another c file.我正在尝试从另一个 c 文件访问一个 c 文件中定义的结构。 The issue is that I cannot use the extern keyword nor can I defined the struct in the header file .问题是我不能使用extern关键字,也不能在 header 文件中定义结构 How do I access the struct defined in abstract.c inside use_abstract.c ?如何访问use_abstract.c内部的abstract.c中定义的结构? Here is a minimally producible example:这是一个最低限度的可生产示例:

abstract.c摘要.c

#include <stdio.h>
#include <stdlib.h>

typedef struct s_strukt {
    int x;
} strukt;

strukt* create_struct() {
    strukt* s = malloc(sizeof(strukt));

    return s;
}

abstract.h摘要.h

#ifndef H_ABSTRACT
#define H_ABSTRACT
struct s_strukt;

#endif

use_abstract.c使用_abstract.c

#include <stdio.h>
#include "abstract.h"

int main() {

    strukt *s = create_struct();
    s->x = 0;

    return 0;
}

Executing the following results in errors gcc use_abstract.c abstract.c :执行以下导致错误gcc use_abstract.c abstract.c

use_abstract.c:6:5: error: use of undeclared identifier 'strukt'; did you mean 'struct'?
    strukt *s = create_struct();
    ^~~~~~
    struct
use_abstract.c:6:5: error: declaration of anonymous struct must be a definition
use_abstract.c:6:5: warning: declaration does not declare anything [-Wmissing-declarations]
use_abstract.c:7:5: error: use of undeclared identifier 's'
    s->x = 0;
    ^
1 warning and 3 errors generated.

There are a few ways of tackling this particular issue, depending on what you're trying to do.有几种方法可以解决此特定问题,具体取决于您要执行的操作。

First, your code seems to be conflating the structure name struct s_strukt with the typedef name strukt .首先,您的代码似乎将结构名称struct s_strukt与 typedef 名称strukt In general, the typedef would live in abstract.h , where it would be available to both client code and to the implementation in abstract.c (and I think that, in general, having a type name that is one letter different from -- and pronounced the same -- as an existing C keyword is going to lead to confusion and dismay).通常, typedef将存在于abstract.h中,它可用于客户端代码和abstract.c中的实现(我认为,通常,类型名称与 -并且发音相同——因为现有的 C 关键字会导致混乱和沮丧)。

If your goal is clear separation between interface and implementation, you can use what are called " opaque structures ".如果您的目标是明确区分接口和实现,则可以使用所谓的“不透明结构”。 This is what you get when you have a type that references a structure the definition of which isn't visible to the calling code (for example, the FILE type used by fopen/fclose/read/write , etc).这就是当您有一个引用结构的类型时得到的结果,该结构的定义对调用代码不可见(例如, fopen/fclose/read/write使用的FILE类型等)。

In abstract.h , you would have:abstract.h中,您将拥有:

#ifndef H_ABSTRACT
#define H_ABSTRACT

typedef struct s_strukt strukt;

strukt *create_strukt(void);
#endif

And in abstract.c , you would have:abstract.c中,您将拥有:

#include <stdio.h>
#include <stdlib.h>

#include "abstract.h"

struct s_strukt {
    int x;
};

strukt *create_strukt() {
    strukt *s = malloc(sizeof(strukt));
    return s;
}

Given the above, you could write use_abstract.c like this and it would compile without error:鉴于上述情况,您可以像这样编写use_abstract.c并且它可以无错误地编译:

#include <stdio.h>
#include "abstract.h"

int main() {
    strukt *s = create_strukt();

    return 0;
}

But there's a problem!但是有问题! Because strukt is an opaque type, if you try to do this in use_abstract.c :因为strukt是一种不透明类型,所以如果您尝试在use_abstract.c中执行此操作:

s->x = 0;

It will fail:它会失败:

use_abstract.c: In function ‘main’:
use_abstract.c:8:6: error: invalid use of incomplete typedef ‘strukt’ {aka ‘struct s_strukt’}
    8 |     s->x = 0;
      |      ^~

A typical solution for this is to implement routines in abstract.c to get/set values in the opaque structure.一个典型的解决方案是在abstract.c中实现例程来获取/设置不透明结构中的值。 Eg, make abstract.h look like this:例如,让abstract.h看起来像这样:

#ifndef H_ABSTRACT
#define H_ABSTRACT

typedef struct s_strukt strukt;

strukt *create_strukt(void);
void strukt_set_x(strukt *s, int value);
int strukt_get_x(strukt *s);

#endif

And abstract.c look like this:abstract.c看起来像这样:

#include <stdio.h>
#include <stdlib.h>

#include "abstract.h"

struct s_strukt {
    int x;
};

strukt *create_strukt() {
    strukt *s = malloc(sizeof(strukt));
    return s;
}

void strukt_set_x(strukt *s, int x) {
    s->x = x;
}

int strukt_get_x(strukt *s) {
    return s->x;
}

And then write use_abstract.c like this:然后像这样写use_abstract.c

#include <stdio.h>
#include "abstract.h"

int main() {
    int val;

    strukt *s = create_strukt();
    strukt_set_x(s, 0);
    val = strukt_get_x(s);
    printf("val is: %d\n", val);

    return 0;
}


But what if you don't want to use an opaque structure?但是如果你不想使用不透明的结构怎么办? Then you would write abstract.h like this:然后你会这样写abstract.h

#ifndef H_ABSTRACT
#define H_ABSTRACT

typedef struct s_strukt {
    int x;
} strukt;

strukt *create_strukt(void);

#endif

Because the structure definition is now in abstract.h , where it's exposed both to the implementation in abstract.c and the client code in use_abstract.c , we no longer need getter/setter functions, because code in use_abstract.c can access structure members directly. Because the structure definition is now in abstract.h , where it's exposed both to the implementation in abstract.c and the client code in use_abstract.c , we no longer need getter/setter functions, because code in use_abstract.c can access structure members直接地。 With the above, abstract.c would look like:有了上面, abstract.c看起来像:

#include <stdio.h>
#include <stdlib.h>

#include "abstract.h"

strukt *create_strukt() {
    strukt *s = malloc(sizeof(strukt));
    return s;
}

And use_abstract.c would look like:use_abstract.c看起来像:

#include <stdio.h>
#include "abstract.h"

int main() {
    strukt *s = create_strukt();
    s->x = 0;
    printf("x is: %d\n", s->x);

    return 0;
}

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

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