ページ 11

インクルードの順番でgccだとエラーになります

Posted: 2012年4月05日(木) 22:16
by L'z
IDEを起動するまでもないちょっとしたものを作りたく、すぐにできるgccを使いました。

するとエラーが山のようにいろいろためしてみるとインクルードが
#include <windows.h>
#include <iostream>
この順ならエラーが出て
#include <iostream>
#include <windows.h>
この順ならコンパイルできます。

それ以外のコードはメイン関数にreturn 0;だけでもおこりました。

VC++2010で試した所問題なく動きましたしネットで適当な例を見ても
windows.hが先に来ているのもあります。

gccバージョンは4.3.0です。

gccを使う時だけインクルード順を気にするのも嫌なので順関係なくコンパイルできるようしたいです。



エラーはすごく多いので表示・非表示を切り替えるようしたかったのですが
その機能が使えなかったためすごく長くなります。
パスの一部を?に置換してあります。
► スポイラーを表示

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 00:20
by tk-xleader
windows.hをインクルードする前に、

#define NOMINMAX

によって、マクロ識別子NOMINMAXを定義してください。

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 01:23
by L'z
できました。
ありがとうございました。

よろしければなぜこれでコンパイルできるようになるのか、なぜVC++だとOKだったのか教えてもらえますか?

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 03:37
by ISLe
L'z さんが書きました:IDEを起動するまでもないちょっとしたものを作りたく、すぐにできるgccを使いました。
Visual C++もコマンドプロンプトからclコマンドでコンパイルすることができますけど。

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 06:33
by beatle
L'z さんが書きました: よろしければなぜこれでコンパイルできるようになるのか、なぜVC++だとOKだったのか教えてもらえますか?
VC++のwindows.hやiostreamとgccのwindows.hやiostreamは中身が同じとは限らず(というか恐らくだいぶ違う)、その辺が影響しているのだろうと思います。

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 07:00
by fulls
効果としては、std内のmin,max関数とwindows.h内のmin,max関数が競合するのをNOMINMAXを定義することでwindows.hのmin,max関数を無効化しているようですね。

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 09:35
by L'z
回答ありがとうございます。
ISLe さんが書きました:
L'z さんが書きました:IDEを起動するまでもないちょっとしたものを作りたく、すぐにできるgccを使いました。
Visual C++もコマンドプロンプトからclコマンドでコンパイルすることができますけど。
できるというのは知っていましたが普通のコマンドプロンプトでなくvisual studioコマンドプロンプトにする必要があるのとVC++でのコンパイルのコマンドを知らなかったのでVC++を入れる前に使っていたgccにしました。

VC++のコマンドプロンプトでコンパイルするときもgccでコンパイルするときと同じオプションが使えるのでしょうか?
beatle さんが書きました:
L'z さんが書きました: よろしければなぜこれでコンパイルできるようになるのか、なぜVC++だとOKだったのか教えてもらえますか?
VC++のwindows.hやiostreamとgccのwindows.hやiostreamは中身が同じとは限らず(というか恐らくだいぶ違う)、その辺が影響しているのだろうと思います。
インクルードファイルの中身が違うんですね。
これはCとかC++とかで完全に決まっているものかと思ってました。
pefs3d さんが書きました:効果としては、std内のmin,max関数とwindows.h内のmin,max関数が競合するのをNOMINMAXを定義することでwindows.hのmin,max関数を無効化しているようですね。
それはNOMINMAXというのとエラー文からなんとなくわかるのですがどうしてこの順の場合はwindows.hのmin,max関数を無効化する必要があるのかと思いました。
iostreamをあとで宣言する場合もstd内min,max関数を無効化する必要がなぜないのか と。
gccのインクルードファイルではすでに定義されている場合のことを考えてなくVC++のものは考えられているということみたいですね。

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 09:43
by beatle
windows.hのmin, maxはマクロですから(エラー文から判断できます)、windows.hをiostreamより先にインクルードすると、iostream内の全部のmin, maxを置き換えちゃうのです。
それに対し、windows.hをあとからインクルードすれば、iostream内のmin, maxは置き換えられませんから、エラーが出なくなる、という仕組みでありましょう。

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 10:26
by softya(ソフト屋)
こういうのはVC++(マイクロソフト製)のiostreamとgccのiostreamが中身が違うので問題が起きます。
windows.h(マイクロソフト製)との相性は自社のVC++(マイクロソフト製)のiostreamを作る時に考慮してますが、gccのiostreamを作るときには特に考慮されていません。
あとwindows.hの歴史が長いというのも問題点の一つでしょう。
L'z さんが書きました:VC++のコマンドプロンプトでコンパイルするときもgccでコンパイルするときと同じオプションが使えるのでしょうか?
同じオプションは使えません。
ただ、複雑なgccのオプションに比べるとシンプルですよ。

「カテゴリ別のコンパイラ オプション (C++)」
http://msdn.microsoft.com/ja-jp/library ... s.80).aspx
「gcc(GNU)のマニュアル」
http://www.geocities.jp/woodwood77777/gcc_gnu.htm

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 12:04
by L'z
beatleさん、softya(ソフト屋)さん 丁寧な説明ありがとうございました。

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月06日(金) 22:45
by ISLe
L'z さんが書きました:できるというのは知っていましたが普通のコマンドプロンプトでなくvisual studioコマンドプロンプトにする必要があるのとVC++でのコンパイルのコマンドを知らなかったのでVC++を入れる前に使っていたgccにしました。
普通のコマンドプロンプトから使えますよ。

Visual Studio コマンドプロンプトが呼び出しているバッチファイルを呼び出しても良いですし、
とりあえずPath,INCLUDE,LIBの3つの環境変数を設定しておけばいつでも使えるようになります。

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月09日(月) 18:50
by L'z
ISLe さんが書きました:
L'z さんが書きました:できるというのは知っていましたが普通のコマンドプロンプトでなくvisual studioコマンドプロンプトにする必要があるのとVC++でのコンパイルのコマンドを知らなかったのでVC++を入れる前に使っていたgccにしました。
普通のコマンドプロンプトから使えますよ。

Visual Studio コマンドプロンプトが呼び出しているバッチファイルを呼び出しても良いですし、
とりあえずPath,INCLUDE,LIBの3つの環境変数を設定しておけばいつでも使えるようになります。

返信おそくなりました。
普通のコマンドプロンプトからも使えるのは知りませんでした。
方法を詳しく知りたいのですが、
「Visual Studio コマンドプロンプトが呼び出しているバッチファイルを呼び出す」というのは
Visual Studio コマンドプロンプトを起動すると最初に表示される「Setting environment for using Microsoft Visual Studio 2010 x86 tools.」という設定を普通のコマンドプロンプトで手動するということですよね。
その設定はVisual Studio コマンドプロンプトのリンク先になっている
%comspec% /k ""C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"" x86
を実行するだけでよいのでしょうか?

環境変数に設定するフォルダは
C:\Program Files\Microsoft Visual Studio 10.0\VC
にあるincludeとlibでいいでしょうか?
pathというのフォルダはここになかったのですがフォルダの場所を教えてもらえませんか?

それとバッチファイルの実行か環境変数の設定はどちらか片方でいいのですか?

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月10日(火) 02:49
by ISLe
ふつうにコマンドプロンプトを開いて、
"C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat"
とコマンドを打てば(x86オプションは指定しなくても良い)、Visual Studio コマンドプロンプトと同じ環境設定が行われます。

コンパイラ(CLコマンド)を使うために必要な環境変数は以下のとおりです。
#Visual C++ 2010 Expressの場合
  • INCLUDE
    【設定】 C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE;C:\Program Files\Microsoft SDKs\Windows\v7.0A\include;
  • LIB
    【設定】 C:\Program Files\Microsoft Visual Studio 10.0\VC\LIB;C:\Program Files\Microsoft SDKs\Windows\v7.0A\lib;
  • Path
    【追加】 C:\Program Files\Microsoft Visual Studio 10.0\VC\BIN;
L'z さんが書きました:それとバッチファイルの実行か環境変数の設定はどちらか片方でいいのですか?
どちらか片方で良いですが、コンパイラ以外のツール等の設定も含まれているのでバッチファイルを実行するほうがお勧めです。


ウチではユーザーフォルダ直下にBinディレクトリを掘って、そこにvcvarsall.batを呼び出すvc10.batというバッチファイルを作って置いてます。
で、そのBinディレクトリにパスを通してあって、
vc10
とコマンドを打ってCLコマンドを使えるようにしてあります。
vc10.batにはDirectX SDKを使うための設定も含めています。
Windows SDKのx64ターゲット用コンパイラを使いたいときもあるので別のバッチファイルを作っておいて必要に応じて環境設定するようにしてます。

Re: インクルードの順番でgccだとエラーになります

Posted: 2012年4月10日(火) 11:36
by L'z
わかりました。

ISLeさん丁寧な説明ありがとうございます。