ページ 11

ファイル分割した際,構造体が未定義になる.

Posted: 2018年1月26日(金) 17:51
by Sado
初めまして(?)、サドです。今回は問題解決に向けて皆さんどうぞ宜しくお願いします。
学校の課題をいじっているので、編集中のソースコードを掲載するのは控えたいと思います。(身バレが怖いので)
VS2015 C言語(c++になっているっぽい?)

今までソースファイルを一つしか使っていなかったので、ファイル分割の練習がてらいろいろな場所で宣言・初期化を行っていた所、main()とは別の関数をまとめたソースファイル内で「式は完全なオブジェクト型へのポインターである必要があります」「C2037:未定義の構造体が指定されています」といったエラーを吐きました。
ここでソリューションのソースファイル構造を説明します......
画像
init.c内で定義・宣言した構造体(もしくはその構造体型の変数?)が未定義とされていますが、同ファイル内で宣言した他のグローバル変数はmain.cでもfunction.cでも問題なく利用できています。
このことからincludeやヘッダでのextern指示子は恐らく問題ないだろうことがわかりますから、構造体の定義に問題があることは予想できるのですが、少しググった程度ではどう弄ってもエラーが解消されませんでした。
(似たようなエラーが違うファイルで起きるだけとか、未定義エラーが増えたとか...)
もっと根本的な、基本的な無知からくるエラーだと思うのですがどうでしょうか?
ご指導のほど宜しくお願いします......

コード:

//include.hの内容
#include "define.h"

//*** 宣言 *** 一部略
extern char readline[];
extern struct strtype_example;
extern struct strtype_example exList[EX_NUM];

//*** 関数群 *** 省略

コード:

//init.cの内容
#include <stdio.h>
#include "include.h"

struct strtype_example {
	char *dataA;
	char *dataB;
};
char readline[N] = { NULL };
struct strtype_example exList[EX_NUM];
//EX_NUMはdefine.hで定義されている

コード:

//function.cの内容(問題箇所を抜粋)
#include <stdio.h>
#include <string.h>
#include "include.h"

int exampleFn() {
	//略
	exList[0].dataA = "abc"; //問題箇所******
	//exList部分が赤波線でマークされ,マウスオーバーで「式は完全なオブジェク(略)」と表示.
	//ここではreadline(char配列)も利用しているが,これはエラーが出ていない.
	//略
	return 0;
}

Re: ファイル分割した際,構造体が未定義になる.

Posted: 2018年1月26日(金) 18:43
by Bull
exList は include.h で

コード:

extern struct strtype_example exList[EX_NUM];
と宣言していますが、このままでは struct strtype_example は不完全型(中身がない)です。
struct strtype_example は init.c で 定義されていますが、funcion.c からは見えません。

コード:

struct strtype_example {
    char *dataA;
    char *dataB;
};
は include.h に記述すると良いでしょう

Re: ファイル分割した際,構造体が未定義になる.

Posted: 2018年1月26日(金) 23:28
by Sado
回答ありがとうございます。
確かに構造体の定義をヘッダに移動させることで、件のエラーが落ち着きました。
とりあえずexternをつければいいや、とヘッダの使い方をググって知ったかぶった私の間抜けですね......
変数や関数の定義・宣言はともかく、構造体の定義に関してのみextern指定子は無効だという考えで間違いないでしょうか?

ひとまずエラーが解決しましたので、スレッドは解決とさせていただきます。
Bullさん、ありがとうございました。

Re: ファイル分割した際,構造体が未定義になる.

Posted: 2018年1月27日(土) 08:22
by Bull
Sado さんが書きました:変数や関数の定義・宣言はともかく、構造体の定義に関してのみextern指定子は無効だという考えで間違いないでしょうか?
そうですね、C/C++言語では型の外部参照はありません。
コンパイラーは別のファイルにある構造体定義を(#include 以外で)読込むようなことはしません。
オブジェクトと関数の外部参照はリンク時に解決されますが、コンパイルはソースファイル単位(正確には翻訳単位)に行われます。ポインターなら不完全型でもいい場合がありますが、構造体のオブジェクトにアクセスするには不完全型ではダメですね。