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

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

ただいまの
回答率

90.51%

  • C

    3690questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C言語の.cファイルと.hファイルに違いはありますか?

受付中

回答 6

投稿

  • 評価
  • クリップ 0
  • VIEW 483
退会済みユーザー

退会済みユーザー

他の言語では外部ファイルも同じ拡張子のソースコードでそれを読みこむのがありますよね。
C言語で拡張子が違くなっているのは何故ですか?

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 6

+8

まずC言語と他の言語を比較してみる。すると最近の他の言語にはモジュールという物があり(詳細割愛)、ほかのモジュールを読み込むための構文が用意されている。モジュールの場合、外部公開するか否かを指定する(通常exportとかexternとかそんなキーワードを使う)ことで、他のモジュールからそのモジュールが読み込めるようになる。

C(そしてC++)ではどうかというとそんな高尚なものは存在しない。あるのは#includeというプリプロセッサマクロで、こいつはただの自動コピペマシーンだ。指定したファイルの中身をそっくりそこにコピペする。

すると困ったことがあって、複数の翻訳単位からincludeされることを想定していないファイルを読み込んでしまうと定義が複数出来上がりリンカーで衝突する。これはまずい。

解決策は

  1. 宣言のみを集めたファイルを作ってそれをincludeする
  2. inlineキーワードを利用して定義が複数出来上がっても同一のものなら衝突しないよう指示する

となる。

ここでヘッダーファイルとは宣言のみを集めたファイルを一般に指す。定義がないことをわかりやすくするため、.hとか.hppとかいう拡張子を利用することが多い。

2の手法は昔のC(C89)だと標準規格では用意されていなかったため、いまでもC言語界隈ではマイナーな解決策だ。しかしC++界隈ではtemplateの存在や名前マングルの問題からヘッダーオンリーライブラリと呼ばれる、2の手法を利用してヘッダーに実装をすべて書いてあるライブラリが流行している。

で、結局ヘッダーファイルとは何だったのか?歴史的変遷ののち、現在では#includeで読み込まれることを想定しているファイル、となる。そしてこれらに対して.hとか.hppとかいう拡張子を利用することが常識である。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+2

拡張子が別れているのは、両者ともC言語のソースコードではあるものの、使い方が違うからです。コンパイラやmakeなどは拡張子の使い分けを前提に動いていますので、違う拡張子にするのであれば手動設定する必要が出てきます。

  • .cファイル…関数や変数の定義を行う。基本的に同じ定義が重複するとリンクできないので、.cファイルを#include対象とすることは通常ない。
  • .hファイル…関数や変数、型の宣言を行う。呼ぶ各箇所で宣言が必要になるので、#includeを使って取り込む(なお、コンパイル前に処理されるマクロや、暗黙を含めinlineな関数、テンプレートなどについては、ヘッダで定義まで行って、そのまま複数ファイルで#includeしても問題ありません)。

他の言語での事例ですが、JavaやC#はコンパイル後のファイル自体が型情報を持っているためそのままコンパイラで処理ができ、ヘッダーは不要です。一方、C言語の場合は「型情報はソースコード内から読み取る」ということになっているので、ソースコードに#includeする形のヘッダーが必要になります。

また、PerlやPHPなどのスクリプト言語は型定義と実装を分けませんので、ヘッダーファイルという概念は存在しません。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

こんにちは。

物事を分かりやすくするための習慣です。
複数の .c ファイルから#includeされるファイルには、 .h との拡張子を付ける習慣です。
これにより、そのソースを読む人は理解が捗ります。
ですので、守る必要はないですが、理由もなく守らないとそのソースを見る人を無駄に混乱させるため嫌がられます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/13 16:57

    では他の言語ではそうなっていないのは何故でしょうか

    キャンセル

  • 2018/07/13 17:14

    別にC言語の方式が唯一無二なベストな方法というわけではないからと思います。
    個人的にはヘッダ・ファイルを手で書く必要があるのは嬉しくはないです。他の一部の言語のように自動でexportしてくれると嬉しいです。でも、互換性維持の観点からそれはかなり難しそうな気がします。

    キャンセル

  • 2018/07/13 17:18

    なにいってんのかわかんね

    キャンセル

  • 2018/07/13 17:19

    他の言語は手で書かないのか
    自動でexportって何
    互換性?何のとこ?

    キャンセル

  • 2018/07/13 20:11

    .h に [1] extern int add1(int x);
    .c に [2] int add1(int x) { return x+1; } とか書くやないですか。
    そーすっとint add1(int x)が都合2回現れる。
    ヘッダの要らない言語では[2]をコンパイルしたときに[1]に相当する"関数を使うひとのための情報(メタ・データとか言う)"を自動生成(export)するですよ。こんなCコンパイラを作ることも可能ですが、それはあくまでコンパイラ・メーカが独自にやることで、他のコンパイラに食わすときはやっぱヘッダが必要。互換性がないので。

    キャンセル

+1

C 言語では、「関数の使用は宣言の後でなくてはならない」という制限があります。
関数 func() を使うに、func() の定義自体を行って宣言しておかなくてはなりません。
※main() は例外です

しかしこれを常に行うのは不可能(ライブラリ関数はソースがありませんからね)なので、前方宣言という機能があります。
関数の型(呼び出しパラメータの数と型、戻り値の型)だけを先に定義して、実装は後回しにするという方法です。これだと、実装の位置に関わらず宣言さえ正しければうまくコンパイルとリンクが行われます。ライブラリ関数の場合はコンパイルがなく、リンクの時点で実装がうまく結合されます。

この宣言のために使われるのが、ヘッダファイル(*.h)です。


前方宣言がなくてもコンパイル・リンクができるような言語もあります。逆に前方宣言を禁止している(必ず実態が利用の前に必要)ことで、コンパイル速度を稼ぐ言語もあります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/13 20:38

    > ※main() は例外です
    いや、main()は、(システム以外から)一般的に呼び出される事が無いからでしょう。

    キャンセル

+1

大体、他の人の書かれた通りなんですが、C言語の場合、歴史を無視できないじゃないかと。
確かに関数の宣言は大切ではありますが、初期の Cでは、宣言無しで使われると引数不明、戻り値 int とみなされていた。それよりもそれぞのソースファイルで共通に参照される 定数とか、別個に定義すると間違えるので、共通ファイルに置かれたじゃないですか?
今時のシステムでは、沢山のファイルを参照してなんて容易ですが、C言語は1990年よりも前だったかと。そして当時でも最新とは言えないシステムで作られたので、他のファイルを参照するにしても指定したファイルのみにした方が、効率が良い、、そんな発想ではないかと思います。(アセンブラ...)

それを今でも引きずっているのが、C言語でしょう。その系譜にありながら、使い勝手向上したのが、Java とか、C#

拡張子については他の人も書かれているように、共通化しておけば、分かり易く使い良い。(特に make ファイルで参照する時に、.c.o なんて定義すれば、かなり省略した書き方ができる)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

違いは無いと言えば無いですね。
.h.c以外の拡張子でも、中身がテキスト形式でC言語の構文で書かれていればコンパイルは可能です。
実際、過去に上記以外の拡張子のソースコードが含まれているプロジェクトで仕事したこともあります。
ただ、コンパイル対象のファイルをMakeFile等に列挙する際に ファイル名.拡張子 とひとつずつ書くよりも
「このフォルダの下の.c全部」と書いた方が楽なので普通は拡張子は揃えます。

ちなみにですが、普通は.hのファイルはコンパイル対象ではありません。
C言語ではxxxx.cというファイルをコンパイルしてxxxx.objのようなオブジェクトファイルを生成し、最後にそれらオブジェクトファイルと必要なライブラリファイルをリンクして実行ファイルを生成します。
先日知人がVisualStudioでxxxx.cからxxxx.hにリネームした後で再度xxxx.cを新規作成した際、xxxx.hがコンパイル対象になってしまいトラブっていました。
(xxxx.hxxxx.cの両方がxxxx.objの生成元となってしまい、後勝ちで上書かれてしまっていた)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/13 17:35 編集

    C言語の#includeは他の言語のimport等のように高度なものではなくて、「『#include ファイル名』と書かれた位置にそのファイルの内容をガバっとコピペしてからコンパイルする」程度の意味です。
    なので、#includeする対象のファイルも拡張子はなんでも良いです。

    キャンセル

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

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

関連した質問

  • 解決済

    File's Ownerとは

    現在Xib関連の操作をしており、色々なサイトでFile's Ownerとクラスをひも付けたりしているのですが、このFile's Ownerとは一体何なのでしょうか? 例えば新たに

  • 受付中

    Mac OS X のターミナル

    terminal.app を使ってファイル操作をする際にデスクトップまで行き、lsコマンドでデスクトップのファイルを表示するとGUIでは見えていない以下の様な形式のファイルが見えま

  • 解決済

    mysql エラー The server quit without updating PID fil...

    以前は使用できていたのですがPCを再起動した際にmysqlのエラーが出るようになってしまいました。 The server quit without updating PID 

  • 解決済

    Google Drive APIsをPythonでいじるための設定をしたい

    前提・実現したいこと Google Drive APIsリンク内容のガイドに沿って進めてstep4のquickstart.pyを実行したところ、以下のエラーメッセージが発生しまし

  • 受付中

    Cyberduckを使って、楽にローカルのファイルと同期する方法

    こんにちは 現在サーバとのFTP通信をCyberduckを介して行っているのですが、現在作成中のコンテンツの編集方法として、 1、ローカルにあるファイルを変更 2、Cyb

  • 解決済

    Xcodeアプリファイルの出力先について(build時)

    Xcodeで開発中のアプリをbuild/runした際に作成される、アプリファイル(ipa)はどこに出力されるのでしょうか? インターネットで調べると、ipaファイルを作成する際に

  • 受付中

    [Swift]ExtAudioFileOpenURL実行時のエラーを解決したい

    背景 SwiftでiPhoneアプリを開発中です。 アプリ内で、m4aからwavへの音声変換を行おうとしています。 以下の記事を参考にしています。 Swift3でCor

  • 解決済

    Use of unresolved identifier 'Init'

    Swift4でFoldingCellというライブラリを使いたいのですが、Githubソースコードをそのままコピーしてもエラーが出てきます。エラーの内容はUse of unresol

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

  • C

    3690questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。