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

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

ただいまの
回答率

88.35%

C言語ヘッダーファイルのインクルードガードで、#defineの書き方について

解決済

回答 7

投稿 編集

  • 評価
  • クリップ 4
  • VIEW 3,721

maisumakun

ユーザーランキング総合1位

C言語を書いていると、大量のヘッダーファイルが必要となるので、多重読み込みの混乱を避けるためにインクルードガードが必要となります。

#pragma onceという標準化されていない方法もあるのですが、移植性のあるやり方としては#ifndef#define#endifの流れとなっています。

もちろん特に問題なく使っていたのですが、あるときこんなヘッダーファイルを見つけてしまいました。

/* define_only.h:自分が書いていたやり方 */
#ifndef DEFINE_ONLY_H_INCLUDED
#define DEFINE_ONLY_H_INCLUDED

/* ヘッダーの中身 */

#endif /* DEFINE_ONLY_H_INCLUDED */

/* define_1.h:新しく見かけたもの */
#ifndef DEFINE_1_H_INCLUDED
#define DEFINE_1_H_INCLUDED 1

/* ヘッダーの中身 */

#endif /* DEFINE_1_H_INCLUDED */

インクルードガードに使う記号定数に値を割り当てることで、何かしらのメリットがあるものなのでしょうか。ご存知でしたらお知らせいただければ幸いです。

(2016/05/17 9:48 追記)

見かけた場所というのが、Ruby処理系のヘッダーファイル内です。検索してもインクルードガード以外に使われていなさそうだし、ほぼ全ファイルで1が#defineされていました。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 7

checkベストアンサー

+4

本題から外れますが、参考までにこういう意見もあるようです。

2016年、C言語はどう書くべきか (後編) | モダンコンパイラが#pragma onceをサポート

Wikipedia[en]: pragma once | Portability によると現在も開発されているメジャーなコンパイラの中で未対応なのはOracle Solaris Studioだけのようです。どこまで移植するかによりますが、C11をターゲットにした今風のC言語にするのであれば、標準には無い#pragma onceを使用しても問題無いかも知れません。


【追記1】

ふと気付いたのですが、ANSIになる前のC言語では、#defineで置換後のテキストが必須だったと言うことはないでしょうか? ANSI規格準拠のK&R第二版では置換後のテキストはありません(和訳本p.112の例)でしたので、ANSIの時点で書かなくてもよくなったと推測できませんでしょうか? もしK&R初版をお持ちの方がいれば、どのように書かれているのか教えて欲しいです。


【追記2】

GNU libtoolのドキュメントの中で、インクリュードガードの例で同じく1と入れているものが載っていました。
http://www.geocities.jp/fut_nis/html/libtool-ja/C-header-files.html
上のドキュメントは移植性が高いヘッダファイルの作り方に関してです。ANSI以降は問題ないはずですので、非ANSIとの互換性のためかにそのようにしているのかも知れません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/17 10:02

    これからC/C++を書く上で、pragmatically(実用的には)それでいいかもしれませんね。

    とはいえ、既存のコードを理解することも確実に欠かせないものではあります。

    キャンセル

  • 2016/05/17 20:01 編集

    > 【追記2】

    おお、凄い。よく見つけたですね。
    推奨されている通りに記述している可能性高そうですね。

    キャンセル

+2

こんにちは。

記憶が定かではないのですが、大昔のCコンパイラで#define FOOのような空定義ができないものがあったような気がします。
そのような古いコンパイラの時代に慣れた人が書いたソースでしたらあり得るかも。

しかし、昔懐かしのLattice Cのアミガ用のマニュアルが有りましたが、これは空定義もサポートしているようですので記憶違いの可能性もあります。(43ページ辺り)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/17 18:22

    「昔は…」説に一票。証拠は無いですけど。

    キャンセル

+1

その定義に意味があるかないか本当のところは、ソースを検索するしかないと思います。
どこかのソースで、

#if DEFINE_1_H_INCLUDED==1
処理
#endif


とかやっているかもしれません。
また別のヘッダーファイルでは、

#define DEFINE_1_H_INCLUDED 2


と定義しているところがあるかもしれません。
ここで一般的な回答を求めても真相は質問者様のソースにしかわかりません。
*.h と *.c を対象に、全ファイル検索をしてみることをお勧めします。
その結果、何も出てこないのであれば、やっぱり意味のないコードだったと言えるのですから。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/17 09:54

    ということで、当該のファイルについて情報を追記しました。

    キャンセル

  • 2016/05/17 10:45

    こちらでも確認してみましたが、意味のある使い方をしているところはなさそうですね。
    値無しの#defineもあるので言語的な制約はないものとして、作者なりの何か将来を見越したコードなのかもしれません。

    キャンセル

0

#ifndef XXXXがXXXXが未定義なら以下を展開するという意味なので、XXXXに数値や何かを割り当てる意味は無いと思いますが、このヘッダーファイルの中やインクルードしているソースでXXXXの値を使っている場合は意味が出てくるかも。
ただ、その数値を何かの間違いだと思って消したり、値を変えてしまうと参照している箇所でおかしなことになる可能性があるので、こういう通常の使い方から外れたやり方は好ましくはないと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

単に「値を何も割り当てずに定義だけするのが気持ち悪いから」みたいな個人的好みを持ってる人が1を割り当てて定義しました…というだけのような気がします(つまりそれ自体に何か特別なトリックがあるとかいう話しではないと思います)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/05/16 18:42

    「値なしの定義文が気持ち悪い」と本当に思ってるのなら、それはC言語の仕様を理解していないということで、それはそれで認識を変えて貰う必要がありますよね。

    キャンセル

  • 2016/05/19 09:37

    すみませんが記載スタイルの好みの問題がどうして仕様理解の話しに発展するのかがよくわかりません。if の { を同じ行に書いても改行してから書いても仕様を理解していないという話しにはならないでしょうし if の処理が単行でもかならず { } を省略せずに記述するのが好みですと言っても仕様を理解していないとは言われない気がしますが、なぜ define で空定義する記述が好みじゃないと仕様理解していない事になるのでしょうか…?
    ちなみに私は空定義使ってますので私の好みだという話しでは無いんですが(笑)ちょっと気になったので…後学のためにもう少し解説して頂けるとありがたいです。

    キャンセル

  • 2016/05/20 17:35

    言い方がまずかったかな。仕様は理解しているかもしれませんからね。
    言いたかったのは、「気持ち悪い」ということから「1」を書くというのは、「感情」からそう決めているので、どうなんだろうなということです。自分の書くコードは空文定義は行わないという「スタイルを通す」のならOKだと思います。(意識の問題です)
    ブロックif文のかっこを改行して書くか書かないかというのはどちらも許可されているので、「スタイルが統一」されていればOKだと思います。
    つまり、スタイル統一という意識からそう書いているのならいいと思いますが、好き嫌いの感情から決めるというのは、プログラミングでは極力廃すべき事ではないかと思うのです。
    C言語の仕様として空文定義が許されているのならそれは無条件に受け入れるべきで、気持ち悪いとかという感情から書き方を決めるのはちょっとおかしいんじゃない?ということです。
    私も、if文のかっこや空白の入れ方など人によってまちまちなので、他人が書いたソースを読むと違和感を覚えることはあります。でも、それはその人がそういうスタイルなんだなと受け入れるしか無いと思っています。でも複数人で1つのプロジェクトをやる場合は、予めある程度のスタイルを決めておいたほうがいいとは思います。ただし、ガチガチにしてしまうとやりにくくなるので柔軟な感じにしたほうがいいでしょうね。

    キャンセル

0

ほとんど回答されていると思いますが。

あまり意味無いと思います。

パターン1:

define で マクロ定義や定数定義のように

define TEST_N  (100)

と後ろに何も書かないと違和感があるためつけた可能性。( 書いた人による。 )

パターン2:
後で定数として何かしらの処理で使うため。

パターン3:
消し忘れ。 "#define ABC 1" をコピペして、 ABCの部分を書き換えたが、割り当てられる値 ( ここでは 1 ) を消し忘れたため。

パターン4:
書いた人が間違って覚えている。(理解している。)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

定義済みか未定義かで判断する場合、複数条件が面倒になるので、その対策として数値を使う場合があったと思います。#ifdefがネストすると読みにくくなりますから。

INCLUDE_A_HとINCLUDE_B_Hの両方が定義されていることを条件にする場合に、単に定義するのではなく1として定義しておいて、INCLUDE_A_H+INCLUDE_B_Hが2と等しいことを条件として使うわけです。

いまなら、defined(INCLUDE_A_H)&&defined(INCLUDE_B_H)でてきるのですが。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る