質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

5回答

5600閲覧

#includeの意味

FfJab

総合スコア17

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2016/12/29 14:12

編集2016/12/29 14:19

ソースファイルのはじめに#include<> や #include ~.hppを記述するやり方は見慣れていて特に何も考えずスルーしていたのですが、最近ソースファイルの途中で#includeを記述しているのを見かけました。

これはどういった技術名?テクニック名?なんでしょうか?
何を行う時に使用するのでしょうか教えてください。
僕が見たのは以下のような使い方です。(うる覚えです)

bbb.cファイル
struct a{
~;
~;
~;
};

a = {
'#include aaaa.h
};

aaaa.hファイル
'#define MACRO(x,y,z) {z,y,z},

extern {
'MACRO(x1,y1,z1)



}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

こんにちは。

私も名前は知らないのですが、時々使います。
#define MACRO(...は、bbb.cファイル側にあるはずです。
aaaa.hファイルには、下記のようなイメージの筈です。

C

1MACRO(x1,y1,z1) 2MACRO(x2,y2,z2) 3MACRO(x3,y3,z3)

#define MACRO(x,y,z) {x,y,z},と定義した場合、aaaa.hは下記のように展開されます。

C

1{x1,y1,z1}, 2{x2,y2,z2}, 3{x3,y3,z3},

これをインクルードした結果、bbbb.cファイルは下記のように展開されます。

C

1struct a{ 2 ~; 3 ~; 4 ~; 5}; 6 7a = { 8{x1,y1,z1}, 9{x2,y2,z2}, 10{x3,y3,z3}, 11};

もしかすると、x1,y1,z1を{"x1","y1","z1"}のような文字列で受け取りたい場合もあるかもしれません。
その時は、`#define MACRO(x,y,z) {#x,#y,#z},
と定義すればできます。
このように「本質的に同じものを異なる形式で解釈したいものが、多数ある時」に使うと便利なテクニックです。

デバッグがたいへんやりにくくなりますので痛し痒しですが、本質的に同じものを書式を変えて何度も書くよりは良いと思います。

投稿2016/12/29 14:26

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FfJab

2016/12/30 04:21

ご回答してくださりありがとうございます! 僕の見たコードをもとに(うるおぼえなのにありがとうございます)、展開後の形を示してくださったのでイメージがしやすく大変助かりました。 >「本質的に同じものを異なる形式で解釈したいものが、多数ある時」に使うと便利なテクニック このテクニックをどういう場合に使うとよいかまで教えていただき大変勉強になりました。
guest

0

プリプロセッサの普通の機能です。

プリプロセッサの#includeディレクティブは、「#include <ファイル名>」または「#include "ファイル名"」の部分をそのファイルの内容に置き換えたものをコンパイラ本体に渡す、それ未満でもそれを超えるものでもありません。インクルードされるファイルにどのようなことが書かれていても、#includeディレクティブをどこで使っても、プリプロセッサは機械的にマージしてコンパイラ本体に渡すので、C/C++言語的な事項に関してはコンパイラ本体にお任せです。

ご存じかと思いますが、マクロの展開、#ifdefディレクティブなどに基づくコードの抑制、#ifディレクティブの右に書かれた定数式の評価などをプリプロセッサが行います。コメント/* */ // の除去をプリプロセッサで行うコンパイラもありますね。

マクロ定義や関数のプロトタイプ宣言、構造体・クラスの宣言をヘッダファイルと呼ばれるファイルに分離して、ソースファイルの先頭部分の#includeディレクティブによってコンパイル時にマージするのは、その方が開発・保守効率が良いゆえの慣習です。#includeディレクティブをソースファイルの最後に持ってきてもプリプロセッサ的には問題ありません。ただ、C++のメンバの定義にはメンバの宣言が先行していなければコンパイラ本体でエラーになるので、そうしない慣例になっているにすぎません。また、同クラス同関数定義をヘッダファイルに書き、複数のソースファイルでインクルードすればリンクエラーになります。

ぶっちゃけ、ヘッダファイルに何を書こうが、#includeディレクティブをどのように使おうが、エラーにならない限り自由です。でも、実際上の約束があることはご存じのとおりです。宣言を手動でいちいち複数のソースファイル間でコピペしていれば保守性が悪いからしません。

よって、エラーにならず保守性が良ければ、ヘッダファイル・#includeディレクティブをどのような利用法も可能だと思います。

gccでは-Eオプション、他のコンパイラでも同様の手段でプリプロセッサ実行だけがなされるので、その結果をご覧になると良くわかるかと思います。

投稿2016/12/29 17:01

naomi3

総合スコア1105

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FfJab

2016/12/30 04:38

ご回答してくださりありがとうございます。 プリプロセッサによって#include ~のファイル内容が記述した場所に展開される(記述する場所はとわない)。 ただし、コンパイラでエラーとならないように記述する箇所にはプログラマ自身で気をつける必要があると理解することができました!
FfJab

2016/12/30 04:39

gccで-Eオプションを利用して結果もみてみたいと思います! 教えてくださりありがとうございます!
guest

0

各種データ値を開発終盤まで正確に値は決められない(たびたび変更しながら調整していく)けど、ファイル化して実行時に読ませるということはしたくない、できれば実行モジュールに埋め込みたい、かといってハードコーディングだとその都度ソースコードを編集しないといけなくなりミスを誘発してしまうのでそれは避けたい、というときに、ソースコードの「データ部分だけを別ファイル」にして、それをソースコードの途中に「埋め込む」という手法をとることがよくあります。その際、データをカンマで区切ったCSVファイルのような形式にすることが多いです。配列や構造体などの代入書式と親和性が高いからです。
データを別のツール(例えばExcelなど)で管理し、それをテキストファイルで出力してソースコードに埋め込む、というように使うことも多いです。

ちなみに、私の場合、その目的のファイルに付ける拡張子は.hではなく.incにすることが多いです。そして、ヘッダーファイルとは呼ばずにインクルードファイルと呼びます。なぜなら、ヘッダーではないからです(ヘッダーファイルと同じ場所でインクルードするとエラーになります)。

これはどういった技術名?テクニック名?なんでしょうか?

すみません。私も聞いたことがありません。

投稿2016/12/30 02:56

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FfJab

2016/12/30 05:05

ご回答してくださりありがとうございました! 「データ部分だけを別ファイル」にして、それをソースコードの途中に「埋め込む」テクニックなんですね。 どういう目的でこのテクニックを使うのかも教えていただきありがとうございます。 「データ部分だけを別ファイル」にしたものは、通常のヘッダファイルと同じように何も考えずに先頭に書くとコンパイルエラーを起こすこともわかりました。このファイルの管理方法については別途考えます。ヘッダファイルと区別して拡張子を変更したほうが僕もわかりやすいと思いました。
guest

0

コンパイラにとって#includeの位置は、重要です。#include は任意のファイルを書かれた場所に展開する機能によりその場所に内容を展開します。
(実際はプリプロセッサが展開してcコンパイラに渡すのですが)

・ファイルincl1.hとincl2.hで値を定義します。 >cat incl1.h int a1; >cat incl2.h char *a2; >cat hoge.c #include <stdio.h>↲ ↲ ・下記のプログラムはコンパイルエラーです。(a2が定義されていない)a2をincl2.hの後にします。 int main(int argc, char *argv[])↲ {↲ #include "incl1.h"↲ a1=1;↲ a2="bhh";↲ #include "incl2.h"↲ }↲ ~

投稿2016/12/29 15:06

編集2016/12/30 01:30
A.Ichi

総合スコア4070

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FfJab

2016/12/30 04:30

ご回答してくださりありがとうございます。 ヘッダファイルがいつも先頭に書かれているのは、ご回答の中にあるコンパイルエラー例をなくすための習慣のようなものだと理解することができました。 いつもおまじないのように先頭でinclude記述をしていましたが意味を理解することができ勉強になりました。
guest

0

テクニックでもなんでもありません。
#include なんちゃら は なんちゃらの内容がそこに書き下されたのと同じ。

なのでたとえば

C++

1// CSV.h ここから 2 1, 2, 3, 4, 3 5, 6, 7, 8, 4// CSV.h ここまで 5 6// use.cpp 7int a[] = { 8#include "CSV.h" 9};

と書けば

C++

1int a[] = { 2 1, 2, 3, 4, 3 5, 6, 7, 8, 4};

ってことになります。

投稿2016/12/29 14:23

編集2016/12/29 14:26
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

FfJab

2016/12/30 04:16

素早く回答してくださりありがとうございます! シンプルで例も出していただいたのでわかりやすかったです。勉強になります!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問