访问另一个 c 文件中定义的结构?
Accessing a struct defined in another c file?
我正在尝试从另一个 c 文件访问一个 c 文件中定义的结构。问题是我不能使用extern
关键字 我也不能在头文件中定义结构。如何访问 use_abstract.c
中 abstract.c
中定义的结构?这是一个最低限度的示例:
abstract.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
#ifndef H_ABSTRACT
#define H_ABSTRACT
struct s_strukt;
#endif
使用_abstract.c
#include <stdio.h>
#include "abstract.h"
int main() {
strukt *s = create_struct();
s->x = 0;
return 0;
}
执行以下结果出错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.
有几种方法可以解决这个特定问题,具体取决于您要执行的操作。
首先,您的代码似乎将结构名称 struct s_strukt
与 typedef 名称 strukt
混为一谈。一般来说,typedef
会存在于 abstract.h
中,客户端代码和 abstract.c
中的实现都可以使用它(而且我认为,一般来说,有一个类型名称这与 - 发音相同 - 有一个字母不同,因为现有的 C 关键字会导致混淆和沮丧)。
如果您的目标是明确区分接口和实现,您可以使用所谓的“opaque structures”。这就是当你有一个引用结构的类型时得到的结果,该结构的定义对调用代码不可见(例如,fopen/fclose/read/write
使用的 FILE
类型等)。
在 abstract.h
中,您将拥有:
#ifndef H_ABSTRACT
#define H_ABSTRACT
typedef struct s_strukt strukt;
strukt *create_strukt(void);
#endif
而在 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;
}
鉴于上述情况,您可以这样写 use_abstract.c
并且编译时不会出错:
#include <stdio.h>
#include "abstract.h"
int main() {
strukt *s = create_strukt();
return 0;
}
但是有个问题!因为 strukt
是不透明类型,如果你尝试在 use_abstract.c
中这样做:
s->x = 0;
它将失败:
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;
| ^~
一个典型的解决方案是在不透明结构中实现 abstract.c
到 get/set 值的例程。例如,使 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
而 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;
}
然后这样写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;
}
但是如果您不想使用不透明结构怎么办?然后你会这样写abstract.h
:
#ifndef H_ABSTRACT
#define H_ABSTRACT
typedef struct s_strukt {
int x;
} strukt;
strukt *create_strukt(void);
#endif
因为结构定义现在在 abstract.h
中,它暴露给 abstract.c
中的实现和 use_abstract.c
中的客户端代码,我们不再需要 getter/setter ] 函数,因为 use_abstract.c
中的代码可以直接访问结构成员。通过以上,abstract.c
看起来像:
#include <stdio.h>
#include <stdlib.h>
#include "abstract.h"
strukt *create_strukt() {
strukt *s = malloc(sizeof(strukt));
return s;
}
而 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;
}
我正在尝试从另一个 c 文件访问一个 c 文件中定义的结构。问题是我不能使用extern
关键字 我也不能在头文件中定义结构。如何访问 use_abstract.c
中 abstract.c
中定义的结构?这是一个最低限度的示例:
abstract.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
#ifndef H_ABSTRACT
#define H_ABSTRACT
struct s_strukt;
#endif
使用_abstract.c
#include <stdio.h>
#include "abstract.h"
int main() {
strukt *s = create_struct();
s->x = 0;
return 0;
}
执行以下结果出错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.
有几种方法可以解决这个特定问题,具体取决于您要执行的操作。
首先,您的代码似乎将结构名称 struct s_strukt
与 typedef 名称 strukt
混为一谈。一般来说,typedef
会存在于 abstract.h
中,客户端代码和 abstract.c
中的实现都可以使用它(而且我认为,一般来说,有一个类型名称这与 - 发音相同 - 有一个字母不同,因为现有的 C 关键字会导致混淆和沮丧)。
如果您的目标是明确区分接口和实现,您可以使用所谓的“opaque structures”。这就是当你有一个引用结构的类型时得到的结果,该结构的定义对调用代码不可见(例如,fopen/fclose/read/write
使用的 FILE
类型等)。
在 abstract.h
中,您将拥有:
#ifndef H_ABSTRACT
#define H_ABSTRACT
typedef struct s_strukt strukt;
strukt *create_strukt(void);
#endif
而在 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;
}
鉴于上述情况,您可以这样写 use_abstract.c
并且编译时不会出错:
#include <stdio.h>
#include "abstract.h"
int main() {
strukt *s = create_strukt();
return 0;
}
但是有个问题!因为 strukt
是不透明类型,如果你尝试在 use_abstract.c
中这样做:
s->x = 0;
它将失败:
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;
| ^~
一个典型的解决方案是在不透明结构中实现 abstract.c
到 get/set 值的例程。例如,使 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
而 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;
}
然后这样写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;
}
但是如果您不想使用不透明结构怎么办?然后你会这样写abstract.h
:
#ifndef H_ABSTRACT
#define H_ABSTRACT
typedef struct s_strukt {
int x;
} strukt;
strukt *create_strukt(void);
#endif
因为结构定义现在在 abstract.h
中,它暴露给 abstract.c
中的实现和 use_abstract.c
中的客户端代码,我们不再需要 getter/setter ] 函数,因为 use_abstract.c
中的代码可以直接访问结构成员。通过以上,abstract.c
看起来像:
#include <stdio.h>
#include <stdlib.h>
#include "abstract.h"
strukt *create_strukt() {
strukt *s = malloc(sizeof(strukt));
return s;
}
而 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;
}