スレッド: [cppll_novice:0792] プリプロセッサとconstの使い分けで

スレッド

[cppll_novice:0792] プリプロセッサとconstの使い分けで

[ | ▲ / | ]
Subject:
[cppll_novice:0792] プリプロセッサとconstの使い分けで
From:
hac43891 <hac43891@...>
Date:
Sun, 23 Jan 2005 23:14:20 +0900
X-Mailer:
Becky! ver. 2.12.01 [ja]
Message-Id:
<20050123231108.AD5F.HAC43891‐at‐rio.odn.ne.jp>
質問ばかりですいません
hacと申します

プログラムコーディングの作法的なものなのですが
みなさん
プリプロセッサとconstとの使い分けってどうなさっていますか?

たとえば、あるプログラムで固定な文字列や数値を持ちたい場合に、
よくヘッダファイル(実装cppでも)にこのような記述をされているかと思います

TEST_A.h --------------

#define STR_DEFAULT_MSG  "testtest"
#define INT_DEFAULT_NUM  10

------------------------

で、よく参考書や、いろいろなサイトをみると
下記のようにしましょうみたいなものをよく見ます
TEST_B.h ---------------

namespace test {

const char * const STR_DEFAULT_MSG = "testtest";
const int   INT_DEFAULT_NUM = 10;

}
------------------------

私自身、下の方がコンパイル時にプリプロセス時重複のエラー
を出せたり、明示的に文字列なのか数値なのかがわかって
いいと思うのですが
双方の短所、長所って実際のところどうなんでしょうか・・・
なんか全体的にTEST_B.hではなくTEST_A.hのように
プリプロセッサでやってしまうことが多いような思うのですが
面倒なだけなのでしょうか・・・
メモリはTEST_A.hの方が少なくて済むとか・・・

どなたか短所、長所をご教授いただけないでしょうか


--
hac <hac43891@...>

[cppll_novice:0793] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0793] Re: プリプロセッサとconstの使い分けで
From:
NAKANO Kouichi <rawpower@...>
Date:
Sun, 23 Jan 2005 23:58:52 +0900
X-Mailer:
Becky! ver. 2.11.02 [ja]
Message-Id:
<20050123233537.46A1.RAWPOWER‐at‐nike.eonet.ne.jp>
In-Reply-To:
792
References:
792
なかのと申します

> プリプロセッサとconstとの使い分けってどうなさっていますか?

C++だけでは不可能なことをする場合にのみ #define を使います。
たとえば、

 #define THROW_PROGRAMMERS_FAULT(message) \
   throw ProgrammersFault(__FILE__, __LINE__, (message))

 void f()
 {
   if (this->is_invalid()) {
     THROW_PROGRAMMERS_FAULT("Invalid situation in f()");
   do_something();
 }

とか

 enum { A, B };
 class AObject { ... };
 class BObject { ... };

 #CREATE_IF(name) \
   case name: \
     return new name##Object;

 switch(code) {
 CREATE_IF(A);
 CREATE_IF(B);
 }

とか。
あと、ライブラリ間で名前が重なってしまっているときの回避に使うとか。

> 双方の短所、長所って実際のところどうなんでしょうか・・・

hacさんの例のような場合では #define ディレクティブには特に長所はないと思
います。逆に、短所は山のようにあると思います。名前空間の汚染、C++の型シ
ステムからの離脱によるバグの誘発、わかりにくい文法エラーの誘発、、#undef
できてしまう、等々。
既存のコードのしがらみやCとのインターフェースで仕方がない場合以外は、
> const char * const STR_DEFAULT_MSG = "testtest";
> const int   INT_DEFAULT_NUM = 10;
のようにするのが絶対にいいと思います。

----------------------
NAKANO Kouichi rawpower@...

[cppll_novice:0797] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0797] Re: プリプロセッサとconstの使い分けで
From:
mori_mi‐at‐itg.hitachi.co.jp <mori_mi@...>
Date:
Mon, 24 Jan 2005 14:15:07 +0900 (JST)
X-Mailer:
FreeML Web Mailer XP; SP2
Message-Id:
<3339591.1106543707375‐at‐www1.local.freeml.net>
In-Reply-To:
793
References:
792 793
こんにちは、森と申します。
cppll_novice は初書き込みです。宜しくお願いします。

const の場合、初期化されるタイミングが少し気になりますので、便乗質問さ
せてください。(hac さんのもう一つの質問 「[cppll_novice:0791] staticな
クラス内メンバについて」とも被ってしまうのですが)また本題とは少しずれ
た話題かもしれませんが御容赦ください。

const なオブジェクトはロードモジュールに埋め込まれると思っています。
例えば const char * const str = "abc"; の場合、ポインタ str と、文字列
"abc" はロードモジュールがメモリにロードされた時点で、そのバイナリイメ
ージは完成しているものと思っています。従って、同一スコープ内の str がポ
イントする文字列のコピーはプログラム中に一つしか存在しないと思います。
これに対して #define によるマクロは使用される度に別のコピーがロードモジ
ュールに埋め込まれるかもしれません。(BCC5.51 など、同一文字列の埋め込み
を一つにしてしまうコンパイルオプションを持つコンパイラもありまが。)

しかし、プリミティブ型ではない場合、実行時にコンストラクタを呼び出して
初期化(構築)する必要があり、埋め込みでない場合があります。また、グロー
バルなオブジェクトの初期化順序は C++ では不定なので、定数オブジェクト
であってもプログラム開始直後のタイミングによっては利用できない可能性が
あります。同様にグローバルなオブジェクトの解体の順序も不定なので、プロ
グラムの終了間際のタイミングによっては利用できないかもしれません。
(#define foo Foo() とすれば、アドレスや参照をとる事以外は上手くいくか
も知れません。また短時間で終了しメモリリークを気にしなくて良い(?)プロ
グラムならば #define foo (*new Foo) で良いかもしれません。)

以下は構築前・解体後の定数オブジェクトを参照するかもしれないコードです。
const struct Foo {...} foo; の代わりに const char* foo = "FOO"; などと
すると、初期化前のタイミングを捕まえる事ができなかったのですが、プリミ
ティブ型(構築・解体が不要な型)の定数は必ず埋め込みになるのでしょうか?
それとも実行時に順序不定に初期化されることもあるのでしょうか?

------------------------------------------------------------------------
-
#include <stdio.h>

const struct Run {
   Run();
   ~Run();
} run;

void main() { puts("main"); }

const struct Foo {
   int f;
   Foo(): f(123456) { printf("Foo constructor, this = %p, f = %d\n",
this, f); }
   ~Foo() { f = 777777; printf("Foo destructor, this = %p, f = %d\n",
this, f); }
   void show() const { printf("Foo show, this = %p, f = %d\n", this,
f); }
} foo;

Run::Run() { printf("Run constructor, &foo = %p\n", &foo); foo.show(); }
Run::~Run() { printf("Run destructor, &foo = %p\n", &foo); foo.show(); }

------------------------------------------------------------------------
-
実行結果
(Run/Foo の構築・解体順序は不定なので、違う結果になるかも知れません。)

Run constructor, &foo = 0040C5BC
Foo show, this = 0040C5BC, f = 0  // foo は未構築!(メモリ枠は埋め込み?)
Foo constructor, this = 0040C5BC, f = 123456
main
Foo destructor, this = 0040C5BC, f = 777777
Run destructor, &foo = 0040C5BC  // foo は解体済み!
Foo show, this = 0040C5BC, f = 777777

[cppll_novice:0795] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0795] Re: プリプロセッサとconstの使い分けで
From:
DENCHU <cppll@...>
Date:
Mon, 24 Jan 2005 12:52:26 +0900
X-Mailer:
Datula version 1.52.01 for Windows
Message-Id:
<E1CsvH8-00007k-00‐at‐deedlian.denchu.jp>
In-Reply-To:
792
References:
792
hac43891さんの<20050123231108.AD5F.HAC43891@rio.odn.ne.jp>から
>プログラムコーディングの作法的なものなのですが
>みなさん
>プリプロセッサとconstとの使い分けってどうなさっていますか?

 私は殆どプリプロセッサかな。
 const の方法だと初期化が面倒そうなんで嫌いなんです。

>プリプロセッサでやってしまうことが多いような思うのですが
>面倒なだけなのでしょうか・・・

 const だと複数のソースで使いたい場合面倒なんじゃないんですか
ね?この辺はやってみたことない(=ちゃんと調べたことない)んですけ
ど…

test_b.h
const char *msg = "foo";

test_a.cpp
#include "test_b.h"

extern void test(void);

int main(void)
{
 printf( "%s_a\n", msg );
 test();
 return 0;
}

test_b.cpp
#include "test_b.h"

void test(void)
{
 printf( "%s_b\n", msg );
}

 これが、リンクエラーになっちゃうという。

--
電柱一家
mailto:cppll@...
http://denchu.jp/

[cppll_novice:0796] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0796] Re: プリプロセッサとconstの使い分けで
From:
cb <sumiaki@...>
Date:
Mon, 24 Jan 2005 13:46:54 +0900
X-Mailer:
Denshin 8 Go V32.1.5.1 on Windows 5.00.2195 Service Pack 4
Message-Id:
<200501240446.j0O4krhE014792‐at‐mx05.ms.so-net.ne.jp>
In-Reply-To:
795
References:
792 795
DENCHU <cppll@...> さん、こんにちは。cb です。

DENCHU> test_b.h
DENCHU> const char *msg = "foo";
DENCHU>
これって、 const char* const msg = "foo"; で普通に使ってるんですが。

当方 VC6SP6です

/**-------------------------------------------------------------
*      川崎 澄明 sumiaki@...
*-------------------------------------------------------------*/

[cppll_novice:0798] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0798] Re: プリプロセッサとconstの使い分けで
From:
DENCHU <cppll@...>
Date:
Mon, 24 Jan 2005 14:22:59 +0900
X-Mailer:
Datula version 1.52.01 for Windows
Message-Id:
<E1Cswgl-0000DR-00‐at‐deedlian.denchu.jp>
In-Reply-To:
796
References:
792 795 796
cbさんの<200501240446.j0O4krhE014792@mx05.ms.so-net.ne.jp>から
>> test_b.h
>> const char *msg = "foo";
>これって、 const char* const msg = "foo"; で普通に使ってるんですが。

 ん…ああ、ごめんなさい。ちゃんと const 指定してあげれば、コンパ
イルは通るんですね。失礼しました。

 ただ、実態は2つ出来ちゃうのかなあ…と思ったらコンパイルオプシ
ョンで結果は変わってきた…難しいな(^^;

--
電柱一家
mailto:cppll@...
http://denchu.jp/

[cppll_novice:0801] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0801] Re: プリプロセッサとconstの使い分けで
From:
hac43891‐at‐rio.odn.ne.jp <hac43891@...>
Date:
Tue, 25 Jan 2005 02:10:34 +0900 (JST)
X-Mailer:
FreeML Web Mailer XP; SP2
Message-Id:
<4327015.1106586634421‐at‐www2.local.freeml.net>
In-Reply-To:
792
References:
792
う〜ん
なんかさっぱりしないです・・

いままで私は
const char * const STR_TEST = "test";

などとしてきましたが
初期化のタイミング?により無効になる場合
がある?のだろうか

static const char * const STR_TEST = "test";
としたほうがいいのかな・・・

やっぱり#define ~~~
の方がいいのかな・・・
なんか安心して使うのが不安になりました(汗

[cppll_novice:0803] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0803] Re: プリプロセッサとconstの使い分けで
From:
DENCHU <cppll@...>
Date:
Tue, 25 Jan 2005 09:25:19 +0900
X-Mailer:
Datula version 1.52.01 for Windows
Message-Id:
<E1CtEWH-0001B3-00‐at‐deedlian.denchu.jp>
In-Reply-To:
801
References:
792 801
hac43891@...さんの<4327015.1106586634421@www2.local.freeml.net>から
>なんかさっぱりしないです・・

 ケースバイケースじゃないですかと思うのですよ。

>const char * const STR_TEST = "test";
>などとしてきましたが
>初期化のタイミング?により無効になる場合
>がある?のだろうか

 無効になることはないかと思いますが、宣言が書いてあるヘッダファ
イルを複数でincludeするような場合には注意が必要になるんじゃないか
な。

>static const char * const STR_TEST = "test";
>としたほうがいいのかな・・・

 好みでしょ。私はヘッダファイルに static 宣言するのは好きじゃな
いので、書きませんが。そのソース内で完結するような定義だったら、
それでもいいかもしれませんね。

>やっぱり#define ~~~
>の方がいいのかな・・・

 コンパイラが置換するだけですし:-)

--
電柱一家
mailto:cppll@...
http://denchu.jp/

[cppll_novice:0807] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0807] Re: プリプロセッサとconstの使い分けで
From:
NAKANO Kouichi <rawpower@...>
Date:
Tue, 25 Jan 2005 20:34:12 +0900
X-Mailer:
Becky! ver. 2.11.02 [ja]
Message-Id:
<20050125203033.59FB.RAWPOWER‐at‐nike.eonet.ne.jp>
In-Reply-To:
801
References:
792 801
なかのと申します

> static const char * const STR_TEST = "test";
> としたほうがいいのかな・・・

C++では明示的に extern としない場合は上記の意味になります。
つまり、何も指定しなければ static をつけたのと同じです。

----------------------
NAKANO Kouichi rawpower@...

[cppll_novice:0808] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0808] Re: プリプロセッサとconstの使い分けで
From:
ishizaka‐at‐piano.interq.or.jp <ishizaka@...>
Date:
Wed, 26 Jan 2005 10:52:50 +0900 (JST)
X-Mailer:
FreeML Web Mailer XP; SP2
Message-Id:
<1606410.1106704370006‐at‐www2.local.freeml.net>
In-Reply-To:
807
References:
792 801 807
cのばやい、変数としてメモリ上に確保されるけど
c++の場合、定数オブジェクトとして直値を埋め込むと
どこかで読んだ記憶が。

ソース元探したけれど失念。すみません。

みちばな

[cppll_novice:0821] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0821] Re: プリプロセッサとconstの使い分けで
From:
hac43891‐at‐rio.odn.ne.jp <hac43891@...>
Date:
Wed, 2 Feb 2005 00:12:35 +0900 (JST)
X-Mailer:
FreeML Web Mailer XP; SP2
Message-Id:
<7604586.1107270755682‐at‐www3.local.freeml.net>
In-Reply-To:
792
References:
792
hacと申します
失礼ではありますが、私の理解力がなく同じ質問を
"C and C++ フォーラム"でもさせていただきました。
その結果、ようやく理解することができました。。
みなさん、どうもありがとうございました。

[cppll_novice:0823] Re: プリプロセッサとconstの使い分けで

[ | / | ]
Subject:
[cppll_novice:0823] Re: プリプロセッサとconstの使い分けで
From:
Takeshi Umeda <noel@...>
Date:
Wed, 02 Feb 2005 03:39:22 +0900
X-Mailer:
Becky! ver. 2.12 [ja]
Message-Id:
<20050202033852.D435.NOEL‐at‐mva.biglobe.ne.jp>
In-Reply-To:
821
References:
792 821
梅田と申します。

本件の議論は、私も漠然と考えていた素朴な疑問についてのもので、大いに興味
をもって読ませていただいておりました。

ついては「ありがとうございました」で終わられてしまうのは残念に思います。

別の場所での議論で解決したということではありますが、どのあたりに疑問が残
り、それをどう理解して解決に至ったのか、簡単にでかまいませんので、メーリ
ングリストの方にも結果報告を頂けませんでしょうか?

以上、よろしくお願いします。

--------------------------------------------
梅田 竹志 <noel@...>

[cppll_novice:0825] Re: プリプロセッサとconstの使い分けで

[ | / ▼ | ]
Subject:
[cppll_novice:0825] Re: プリプロセッサとconstの使い分けで
From:
DENCHU <cppll@...>
Date:
Thu, 03 Feb 2005 11:04:58 +0900
X-Mailer:
Datula version 1.52.01 for Windows
Message-Id:
<E1CwWMe-0002z3-00‐at‐deedlian.denchu.jp>
In-Reply-To:
823
References:
792 821 823
Takeshi Umedaさんの<20050202033852.D435.NOEL@mva.biglobe.ne.jp>から
>別の場所での議論で解決したということではありますが、どのあたりに疑問が残
>り、それをどう理解して解決に至ったのか、簡単にでかまいませんので、メーリ
>ングリストの方にも結果報告を頂けませんでしょうか?

 元記事を投稿された方がいらっしゃらないので何とも言えませんが、
http://forums.belution.com/ja/cpp/000/028/62s.shtml
 この話題のスレッドじゃないかと思います。

 C++ か C かで判断されるように考えられたみたいですね。

--
電柱一家
mailto:cppll@...
http://denchu.jp/

Navigation

検索

[検索ヘルプ]

Maintener: Tietew <www.tietew.jp>
Powered by Ruby on Rails, Mongrel, PostgreSQL, and Hyper Estraier.
click here