あるcファイルで定義されている構造体に別のcファイルからアクセスしようとしています。問題は、extern
キーワードを使用できず 、ヘッダーファイルで構造体を定義できないことです。abstract.c
内部で定義された構造体にアクセスするにはどうすればよいuse_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
use_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
(一般に、タイプ名は-とは1文字異なり、同じように発音されます-と既存のCキーワードは、混乱と失望につながるでしょう)。
インターフェースと実装を明確に分離することが目標である場合は、「不透明な構造」と呼ばれるものを使用できます。これは、呼び出し元のコードに定義が表示されない構造を参照する型がある場合に得られるものです(たとえば、FILE
によって使用される型fopen/fclose/read/write
など)。
では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
は不透明(OPAQUE)型なので、これを実行しようとすると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
は、不透明な構造で値を取得/設定するためのルーチンを実装することです。たとえば、次のように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
ため、コードイン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;
}
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加