【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.20582

#define 初心者ですみません
投稿者---樹(2005/04/10 14:57:41)


#define _____ _____

では無く。ただ単に定数名だけを書いた時とゆうのはどんな処理なんでしょうか?

#define _____    この様なやつです。

>> おでんさん
openGLの実装ができ、なんとかCの書式で絵を描くのに成功したもようです。(WW cocoaはもうしばらく取っておこうと思います。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:#define 初心者ですみません 20588 おでん 2005/04/10 18:28:24
<子記事> Re:#define 初心者ですみません 20613 nop 2005/04/11 17:21:16
<子記事> ご迷惑かけます 20616 2005/04/13 01:32:03
<子記事> 皆さんどうも、理解できたかもしれません。 20621 2005/04/13 17:43:28
<子記事> Re:#define 初心者ですみません 20627 NykR 2005/04/15 22:46:50


No.20588

Re:#define 初心者ですみません
投稿者---おでん(2005/04/10 18:28:24)


>#define _____ _____
>
>では無く。ただ単に定数名だけを書いた時とゆうのはどんな処理なんでしょうか?
>
>#define _____    この様なやつです。
>

#ifndef COMFUNC_HPP
#define COMFUNC_HPP
/*******************************************************************************
    comfunc.hpp:
*******************************************************************************/
// $Id:$
//
inline void ClearMemory(void * ptr, unsigned int siz )
{
#ifdef _WIN32
    memset((char *)ptr, 0, siz);
#else
    bzero((char *)ptr, siz);
#endif
}
//
#endif



のような使い方をします。

最初の
#ifndef COMFUNC_HPP
#define COMFUNC_HPP
は、もし"COMFUNC_HPP"が定義されていなければ、"COMFUNC_HPP"を定義します。
最初の#ifndefに対応する#endifがファイルの最後にあるので、
"COMFUNC_HPP"が定義されていればこのヘッダファイルは展開されません。
これは、同じヘッダファイルを二度展開しないための常套手段です。

また、関数内の#ifdefは、"__WIN32"が定義されていれば、
memset((char *)ptr, 0, siz)がコンパイルされ、
定義が無ければ、bzero((char *)ptr, siz);がコンパイルされます。


>>> おでんさん
>openGLの実装ができ、なんとかCの書式で絵を描くのに成功したもようです。(WW cocoaはもうしばらく取っておこうと思います。


私のほうに少し勘違いがあったようです。申し訳ありませんでした。


この投稿にコメントする

削除パスワード

No.20603

Re:#define 初心者ですみません
投稿者---樹(2005/04/11 13:24:57)


毎回毎回有り難うございます、おでんさん。

???
謎が沢山あります、すみません・・orz
1つずつ質問していきたいのですが・・・よろしくお願いします。

1>>この"COMFUNC_HPP"と言うものはどのような扱いを受けているのです
   か? 何かと置き換えた訳でもなく、ソースでも使われていない様
   なので・・・・・


この投稿にコメントする

削除パスワード

No.20605

Re:#define 初心者ですみません
投稿者---REE(2005/04/11 13:43:39)


このようなdefineは、何かに置き換えるためではなく、スイッチとして使用しています。
例えば、定義してあればON、定義していなければOFFです。



この投稿にコメントする

削除パスワード

No.20611

Re:#define 初心者ですみません
投稿者---樹(2005/04/11 14:25:35)


REEさん初めまして、よろしくお願いします。
スイッチですか!!なるほど!。すっきりしました。
・・・?そーすると、この"COMFUNC_HPP"のように、#defineで定義する(スイッチする)モノと言うのは、ヘッダと考えてよろしいのですかね?

すみません、いつの間にか多くの方にたくさんのレスを頂いているようです。有り難うございます・・・読むのに時間がかかると思われますが、よろしくお願いします(,,_,,)




この投稿にコメントする

削除パスワード

No.20609

Re:文字・モノクロからの脱却。
投稿者---おでん(2005/04/11 14:03:32)


>毎回毎回有り難うございます、おでんさん。
>
>???
>謎が沢山あります、すみません・・orz
>1つずつ質問していきたいのですが・・・よろしくお願いします。
>
>1>>この"COMFUNC_HPP"と言うものはどのような扱いを受けているのです
>   か? 何かと置き換えた訳でもなく、ソースでも使われていない様
>   なので・・・・・

以下のファイルがあったとき。

ヘッダファイル:comfunc.h

#ifndef COMFUNC_H
#define COMFUNC_H

[省略]

//
#endif

ヘッダファイル:aa.h

#include "comfunc.h"

#define ONE 1

ソースファイル:a.c

#include "comfunc.h"
#include "aa.h"

ソースファイルa.cで両方のヘッダファイルを取り込んでいる。


この状態でa.cをコンパイルします。
1.コンパイル開始時には、"COMFUNC_H"は定義されていません。
2.コンパイラは、#include "comfunc.h"の行を見てヘッダファイルをその場所に展開します。
 この時点では、#ifndef COMFUNC_H の結果は真(定義されていない)となります。
3.この時点で、"COMFUNC_H"が定義されます。→#define COMFUNC_H
4.次に、コンパイラは、#include "aa.h"の行を見てヘッダファイルをその場所に展開します。
 しかし、"COMFUNC_H"が定義されているので、#ifndef COMFUNC_H の結果が偽(定義されている)と
 なるためcomfunc.hは展開されません。#define ONE 1の行は、aa.h内での定義なので展開されます。

簡単な例で示しましたが、実際にはヘッダファイルの取り込みはもっと複雑な状態が起こりえます。
なので、そのための予防策として上記のような定義をします。


標準ライブラリ(stdio.h etc)などのヘッダファイルを見てみることをお勧めします。

ちなみに私の使っている環境のstdio.hの定義部は・・・

#ifndef _STDIO_H_
#define _STDIO_H_

/* All the headers include this file. */
#include <_mingw.h>

以下略



あまりうまい説明じゃないけど、分かりますか?


この投稿にコメントする

削除パスワード

No.20610

Re:#define 初心者ですみません (^^;
投稿者---おでん(2005/04/11 14:08:08)


すみません、また題名間違えた。


この投稿にコメントする

削除パスワード

No.20604

Re:#define 初心者ですみません
投稿者---樹(2005/04/11 13:43:30)


2>>#ifndef COMFUNC_HPP
   #define COMFUNC_HPP

   この2行は『もし"COMFUNC_HPP"を定義してないならば
         "COMFUNC_HPP"を定義しろ』
   と言う意味でよろしいでしょうか?
   それとも#ifndefだけでこう言う意味になりますか?

3>>#endif
   は『#defineで定義していたモノをここで終らせろ』と言う意
   味で理解してよろしいでしょうか?


この投稿にコメントする

削除パスワード

No.20607

Re:#define 初心者ですみません
投稿者---REE(2005/04/11 13:46:57)


#ifndef COMFUNC_HPP と #endif はセットになっていますので、別々に考えると分からなくなります。
#ifndefの時点でCOMFUNC_HPP が定義されていなければ、この間の全ての行が有効になり、
定義されていれば、逆に無効になります。



この投稿にコメントする

削除パスワード

No.20608

Re:#define 初心者ですみません
投稿者---Ban(2005/04/11 13:59:23)


2)

・「もし"COMFUNC_HPP"の定義がなければ、対応する #endif までを解釈しろ」
と、
・「"COMFUNC_HPP"を定義しろ」
の2行です。
対応関係はむしろ #ifndef と #endif で、# define はあまり関係ないです。

>   それとも#ifndefだけでこう言う意味になりますか?
なりません。
#ifndef は大雑把に言って、
「もし〜の定義がなければ対応する #endif までを解釈しろ」です。
#ifndef COMFUNC_HPP は、#if !defined(COMFUNC_HPP) と一緒。


3)
「ifndef の終わりはここまでだ」




C の(擬似)ソースでイメージするならこんな感じ?

if(! defined(COMFUNC_HPP)){ /* ifndef COMFUNC_HPP */
    define(COMFUNC_HPP);
} /* endif */





この投稿にコメントする

削除パスワード

No.20613

Re:#define 初心者ですみません
投稿者---nop(2005/04/11 17:21:16)


>#define _____ _____
>では無く。ただ単に定数名だけを書いた時とゆうのはどんな処理なんでしょうか?
>#define _____    この様なやつです。

置換後の文字がないだけです。


[例]
#define  IN
#define  OUT

/* ----------------------------------------
    fnc
    引数
         [入力] int    a : 整数を受ける
         [出力] int *  b : 整数2を出力
    戻り値
        int : 整数1を返す
---------------------------------------- */
int fnc( IN int a, OUT int *b );




この投稿にコメントする

削除パスワード

No.20616

ご迷惑かけます
投稿者---樹(2005/04/13 01:32:03)


すみません。皆さんの解説を何度読み返して行っても、何か引っかかると言うか、これ!と言った答えをつかめずに居ます・・・orz
皆さんそれぞれの解説から一つのものにたどり着けないでいます・・・orz
皆さんの解説を理解するため、恐縮ながら、もう一つ質問があるので、よろしかったら答えをください・・・ご迷惑かけます。

ここでの『定義』&『定義されるもの』と言うのはどんなものなのでしょうか?
1>ヘッダのようなものになるのでしょうか(内容有りのもの)?
2>ただ単に名前(それぞれ違う番号)のつけられたスイッチのようなも
  のなのでしょうか。
3>その他


この投稿にコメントする

削除パスワード

No.20617

Re:ご迷惑かけます
投稿者---Ban(2005/04/13 02:08:55)


ファイル・ヘッダ云々はいったん忘れた方が分かりやすい気もします。

他の方から挙げられているヘッダの話は「一般的な使い方の例」であって、
マクロの機能自体とは直接関係ありません。
また、(もしかすると)#include などと比較されているかもしれませんが、
共にプリプロセッサに対する命令だという以上の深い関連はないです。
# 使い方の例としては補完しあったりしますが、機能的には独立してます。

少なくとも「ヘッダ」と「マクロ」を同列で見るのは無理があるかと。


マクロには、単純な文字列置換機能の他に、その置換用の文字列を
比較したり、定義されているかを確認する機能もあるのです。

ここでは、その機能を使って、「名前」が定義されているか(有効か)否か
を (defined/ifdef/ifndef) でチェックしているだけで、
値があろうがなかろうが、同じだろうが関係ありません。


こんな感じでどうでしょう。
#define FLAG  2

#if FLAG == 2
   /* ここはコンパイルされる */
#else
   /* ここはコンパイルされない */
#endif

#if FLAG == 0
   /* ここはコンパイルされない */
#endif

#ifdef FLAG
   /* ここはコンパイルされる */
#else
   /* ここはコンパイルされない */
#endif

#if defined(FLAG)
   /* ここはコンパイルされる */
#endif

#ifndef FLAG   /* 'n' は not の'n' */
   /* ここはコンパイルされない */
#endif


このよう(FLAG)に値があってもかまいませんし、
その「名前」が定義されているかいないかをチェックする用法の場合、
その値が何であろうと無関係なので、特に指定しなくてもかまわないのです。



この投稿にコメントする

削除パスワード

No.20619

Re:ご迷惑かけます
投稿者---shu(2005/04/13 11:09:24)


>ここでの『定義』&『定義されるもの』と言うのはどんなものなのでしょうか?

樹さんなら、どんなものだと『仮定』しますか?

それを考えながら、(目的を持って)読みなおしてみる。
C言語というより、日本語の読む力。


この投稿にコメントする

削除パスワード

No.20621

皆さんどうも、理解できたかもしれません。
投稿者---樹(2005/04/13 17:43:28)


考えが一つにまとまった気がします。
cで何か書いてみますので、考えが正しいか否か皆さんご判断よろしくお願いします。お読みになった方はレスください(,,_,,)

1>>#ifndef(定義が"無ければ!"#endifまでコンパイル・定義があれば
       #endifまでコンパイルしない)
   #define(定義されていれば何もせず、そうでなければ定義します
       『ここでは真の#ifndefを通ってくるので定義される』)
      〜略〜
   #endif(終わり。。)

     ↓

2>>#ifcef(定義が"あれば"#endifまでコンパイル・定義が無ければ
       #endifまでコンパイルしない)
      (ここでは#defineで定義する必要が無い!)
      〜略〜
   #endif

2 = 以前定義されているか否か分かりにくい時・選択により定義されてい
  るか否かが変化する時等に使う。
1 = 定義されていると分かっている時に使う。
と、理解しましたが大丈夫でしょうか?よろしくお願いします。



この投稿にコメントする

削除パスワード

No.20622

Re:皆さんどうも、理解できたかもしれません。
投稿者---RiSK(2005/04/14 23:27:23)


>考えが一つにまとまった気がします。
>cで何か書いてみますので、考えが正しいか否か皆さんご判断よろしくお願いします。お読みになった方はレスください(,,_,,)
>
>1>>#ifndef(定義が"無ければ!"#endifまでコンパイル・定義があれば
>       #endifまでコンパイルしない)
正しい。

もし XXX が定義されていなければ(この範囲をコンパイルする)。
if not defined XXX(, compile this region).

と読めば OK.

>   #define(定義されていれば何もせず、そうでなければ定義します
>       『ここでは真の#ifndefを通ってくるので定義される』)
>      〜略〜
意味不明。

XXX を定義する。
define XXX.

と読めば OK.
これ以降 #ifdef XXX が出ればコンパイルされるし,
#ifndef が出ればコンパイルされない。


>2>>#ifcef(定義が"あれば"#endifまでコンパイル・定義が無ければ
>       #endifまでコンパイルしない)
正しい。

>      (ここでは#defineで定義する必要が無い!)
意味不明。定義(#define XXX)されていれば,コンパイルするし
されてなければコンパイルする。
定義するしないはプログラマによるし,
インクルードすればヘッダファイルによって定義されるかもしれない。
状況による。


>2 = 以前定義されているか否か分かりにくい時・選択により定義されてい
>  るか否かが変化する時等に使う。
>1 = 定義されていると分かっている時に使う。
>と、理解しましたが大丈夫でしょうか?よろしくお願いします。

全然大丈夫ではないです。
「定義されて(いる|いない)ときにコンパイル(する|しない)」それだけ。


ex.
・デバッグバージョンではコンパイル(したい|したくない)
#define DEBUG されているときに #ifdef〜#endif までをコンパイル(する|しない)


樹さんに質問

・二重インクルードすると問題が出る。
二回目以降はコンパイルしたくない(おでんさんの例)。

- comfunc.hpp
#ifndef COMFUNC_HPP
#define COMFUNC_HPP
int i;
#endif

- hoge.c
#include "comfunc.hpp"
#include "comfunc.hpp"

とある時,初めの #include を展開した hoge.c は次のようになります。

- hoge.c
int i;
#include "comfumc.hpp"

そして,次の #include を展開するとhoge.c はどうなると思いますか?

- hoge.c
int i;
int i;

- hoge.c
int i;

のどちらですか?



この投稿にコメントする

削除パスワード

No.20629

Re:皆さんどうも、理解できたかもしれません。
投稿者---樹(2005/04/16 09:37:37)


RiSKさん初めまして。
- hoge.c
int i;
だと思われます・・・なんとかココまでは皆さんのおかげでイメージできます。たぶん合ってると思うのでこのまま進めますが、
一番引っかかる所は・・・・・

#ifndef xxx
#define xxx

と、#ifndef xxxでxxxが定義されている・ないを判断した後に、
    〜"何故!"#defineで定義し直すのでしょうか?〜
イメージがつかめません・・・・



この投稿にコメントする

削除パスワード

No.20631

ん〜。分かったかもしれません。。
投稿者---樹(2005/04/16 09:53:25)


なるほど、二重に定義しないためですね。(たぶん)
#ifndefの後に#defineが付いている訳・・・↓

#ifndef で判断した時:真→コンパイルされる。定義が以前に出てないと
              判断されコンパイルされているので、定義し
              てやる必要があるので#defineで付いている
                (定義してやる必要があるソースの場合)
           :偽→コンパイルされずに空白化される

おk?ですか?!!!


この投稿にコメントする

削除パスワード

No.20633

Re:皆さんどうも、理解できたかもしれません。
投稿者---shu(2005/04/16 11:00:44)


#ifdefと#ifndefというものがあります。
#ifdefと#ifndefの違いはわかりますか?

詳しい事は、調べればどこかで見つかると思います。


この投稿にコメントする

削除パスワード

No.20634

Re:皆さんどうも、理解できたかもしれません。
投稿者---樹(2005/04/16 11:38:53)


if not define ではない方ですよね!。
if defined? と言う事で、使い方は #ifndef の反対だと理解しましたが・・・『定義があれば#endifまでコンパイル、無ければ空白化』・・・
基本的には合ってますか?
とりあえず調べてみます!。



この投稿にコメントする

削除パスワード

No.20639

Re:皆さんどうも、理解できたかもしれません。
投稿者---RiSK(2005/04/16 14:31:15)


>- hoge.c
>int i;          
>   だと思われます・・・なんとかココまでは皆さんのおかげでイメージできます。

OK です。

>#ifndef xxx
>#define xxx
>
>と、#ifndef xxxでxxxが定義されている・ないを判断した後に、
>    〜"何故!"#defineで定義し直すのでしょうか?〜

「し直す」が引っかかりますね。
すでに定義されていなければ定義するだけです。

じゃあ,逆に考えてみましょう。

樹さんに質問

- comfunc.hpp
#ifndef COMFUNC_HPP
int i;
#endif

- hoge.c
#include "comfunc.hpp"
#include "comfunc.hpp"

とある時,初めの #include を展開した hoge.c は次のようになります。

- hoge.c
int i;
#include "comfunc.hpp"

そして,次の #include を展開するとhoge.c はどうなると思いますか?

- hoge.c
int i;
int i;

- hoge.c
int i;

のどちらですか?



この投稿にコメントする

削除パスワード

No.20645

こっちだと思われます。
投稿者---樹(2005/04/16 22:50:34)


RiSKさんに手取り足取りです・・・有り難うございます。

- hoge.c
int c;
int c;
  だと思われます。。。
#define なんか分かって来てます!。
ココまで分かればこっちのもんですかね!。


この投稿にコメントする

削除パスワード

No.20646

Re:こっちだと思われます。
投稿者---RiSK(2005/04/16 23:20:11)


>- hoge.c
>int c;
>int c;
>  だと思われます。。。

OK です。

>#define なんか分かって来てます!。
>ココまで分かればこっちのもんですかね!。

そうですね。次の質問に正しく答えられれば
#ifndef 〜 #define 〜 #endif と
それを利用した「インクルードガード」を理解したことになるでしょう。

#define COMFUNC_HPP 有りの時,コンパイルエラーになりますか?
>- hoge.c
>int c;

#define COMFUNC_HPP 無しの時,コンパイルエラーになりますか?
>- hoge.c
>int c;
>int c;

#define COMFUNC_HPP は必要ですか?


この投稿にコメントする

削除パスワード

No.20648

Re:こっちだと思われます。
投稿者---樹(2005/04/17 02:26:49)


インクルードガードですか!?凄い名前ですね!。
ご質問の内容が正確には把握できなかったんですけれども、私的に解釈しますと。

前者も後者もコンパイルは通るものと思われます。
前者には #define COMFUNC_HPP が無いとコンパイルエラーになると思われます(必要)。
    どうでしょうか?


この投稿にコメントする

削除パスワード

No.20658

Re:こっちだと思われます。
投稿者---RiSK(2005/04/17 22:20:21)


>前者も後者もコンパイルは通るものと思われます。

実際にやってみましょう。その方が覚えます。

>    どうでしょうか?

だいたい OK ですね。
あとはツリーを読み返してください。
今なら私以外の方のレスもだいぶ理解できると思いますよ。
とりあえず,このツリーでの私の書き込みはここまで。


この投稿にコメントする

削除パスワード

No.20660

注!皆さん読んで下さい・・・有り難うございました
投稿者---樹(2005/04/17 23:27:02)


わは〜〜〜。
なんとか理解できた模様です(wwwwwww
(こっちの話〜理解しようとしていたソースも理解できてきました。まだまだ長いソースを読んでるので先は長いのですが・・・・)
後は私のコーディングの腕次第ですね!
皆さんのレスを完璧に理解した訳ではないのでこれからですが・・・ココで皆さんのお力添えをSTOPしようと思います。(あまり長々とレスを繰り返すと管理人さんに怒られそうで・・・・・・)
本当に有り難うございました・・・これからもよろしく御願いします。
また近々にお世話になると思われますのでよろしく御願いします。
本当に、有り難うございます。


この投稿にコメントする

削除パスワード

No.20627

Re:#define 初心者ですみません
投稿者---NykR(2005/04/15 22:46:50)


>#define _____ _____
>
>では無く。ただ単に定数名だけを書いた時とゆうのはどんな処理なんでしょうか?
>
>#define _____    この様なやつです。

“無”(というか空白)に置換されて消えます。

#include <stdio.h>

#if 1 // 非0のときデバッグモード

#   define  DEBUG_WRITE fprintf

#else 

#   define  DEBUG_WRITE

#endif

int main(void)
{
  // 下の文は
  // デバッグモード時 :  fprintf(stderr, "デバッグモードの時出力されます\n");
  //                     標準エラー出力に出力
  // デバッグモードでないとき:  (stderr, "デバッグモードの時出力されます\n");
  //                            カンマ演算子式、まともなコンパイラなら
  //                            存在しないのと同じように扱うはず。
  //                            警告ぐらいは出るかもしれない。
  // となる
  DEBUG_WRITE(stderr, "デバッグモードの時出力されます\n");
  return 0;
}



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧