26/01/29 10:53:12.91 YJ+F37lYM.net
C言語では、const int g_a = 5; と書いても、obj ファイルの中では、
g_a がマングル化されてなかったので、const 修飾されているかの情報が
obj ファイルの中では失われていた。
だから、ある翻訳単位 A では、
int g_a = 5;
と変数 g_a を定義し、別の翻訳単位 B では、
extern const int g_a;
と変数 g_a を宣言することも可能で、
その意味は、翻訳単位Bでは、書き換えないが、
別の翻訳単位(Aなど)では、書き換える可能性がある、ということだった。
しかし、C++ では、const int g_a; と宣言された変数 g_a は、
どの翻訳単位でも書き換えられなくする設計となっている
(objファイルの中で名前がマングル化されているのでそれが可能となった)。
その結果、C言語では、g_a をマクロ的には扱ってはならないが、
C++ では、g_a をマクロ的に扱ってもいいという事になる。
これらの現象は、obj ファイルの中で変数名 g_a がマングル化されるかどうかと
切っても切れないような関係にある。
991:はちみつ餃子
26/01/29 11:22:58.87 hMM3WHI30.net
「マクロ的」という言い回しはかなり変なのでやめたほうがいいと思うよ。
992:デフォルトの名無しさん
26/01/29 11:51:42.49 QeUvzik40.net
> その意味は、翻訳単位Bでは、書き換えないが、
> 別の翻訳単位(Aなど)では、書き換える可能性がある、ということだった。
いいえCでもC++でも未定義動作です
「マングル化」や「マクロ的」の珍妙な独自用語も含めて、
独自解釈を確認もせずに垂れ流されると迷惑なのでやめてほしい
993:デフォルトの名無しさん
26/01/29 12:22:07.67 7sXa6UKh0.net
宣言をヘッダに書いて異なる翻訳単位間で共有する意図が分かってなさそう
994:デフォルトの名無しさん
26/01/29 13:45:28.02 YJ+F37lYM.net
C 言語の場合、const属性と翻訳単位を超えたglobal 変数の共有に関して、
1つの翻訳単位における以下のような関数呼び出しと似たような
使い方も想定している可能性がある :
void g()
{
int a = 5;
f(a);
a = 6;
f(a);
}
void f( const int &a );
-----------------------
(翻訳単位A)
int g_a = 5;
// g_a は書き換え自由。
(翻訳単位B)
extern const int g_a;
// g_a は書込み禁止で読み込みのみ可能。
995:デフォルトの名無しさん
26/01/29 13:51:45.15 YJ+F37lYM.net
>>986
そのやり方は推奨される事だと言われているし、理解はできる。
(1)
C 言語で、const が付いてない global 変数 g_b の場合 :
(xxx.cpp)
#includde "xxx.h"
int g_b = 5; //定義
(xxx.h)
extern int g_b; //宣言のみ。
(2)
C++ 言語で、const が付いた global 変数 g_a の場合 :
(t1.cpp)
#includde "xxx.h"
(t2.cpp)
#includde "xxx.h"
(xxx.h)
//マクロ定義なのでオブジェクトの定義ではない :
const int g_a = 5; //マクロ定義風
----------
↑において、(2) の書き方は、古い C 言語のコンパイラだと、
obj のリンクして exe にする段階で g_a が二重定義エラーを起こすかもしれない。
996:デフォルトの名無しさん
26/01/29 14:11:34.91 7sXa6UKh0.net
>>987
g_aの宣言はA.hで行う
extern const int g_a; とするか extern int g_a;とするかの選択が強制される
B.cでg_aにアクセスする必要があるときにはA.hをincludeする
絶対にB.cにextern const int g_a;と書いてはいけない
これは作法の範疇だよ
作法を破れば何でもできるさ
997:デフォルトの名無しさん
26/01/29 14:18:34.04 8yDd8ZBUM.net
科学的アプローチでプログラミング言語を習得しようとするバカ
998:デフォルトの名無しさん
26/01/29 14:21:34.89 YJ+F37lYM.net
>>989
C++の const int g_a = 5;
は、「定義」ではなく、マクロ的に振舞うことが有り、
ヘッダの中で定義しても構わなかったはず。
ところが、C 言語では、処理系依存ではあるが、
基本的には、そうはいかず、原則としてextern を付けないと
いけないし、「= 5」の初期化子は、書いてはいけない。
999:デフォルトの名無しさん
26/01/29 14:23:32.95 YJ+F37lYM.net
Microsoftの「Standard C」という規格では、
int g_a;
と書くと、「共有オブジェクト」になり、複数の翻訳単位で
書いても多重定義エラーにはならない事になっているはず。
1000:はちみつ餃子
26/01/29 14:30:26.56 hMM3WHI30.net
>>988
定義だしオブジェクトだよ……
C++ では const は extern をつけなければ内部リンケージなのでその場合は二重の定義にはならない。(ODR に違反しない)
1001:デフォルトの名無しさん
26/01/29 14:32:19.60 7sXa6UKh0.net
>>991
>C++の const int g_a = 5;
>は、「定義」ではなく、マクロ的に振舞うことが有り、
>ヘッダの中で定義しても構わなかったはず。
そのヘッダを複数の翻訳単位からincludeするとリンカーエラになるよ
staticつけるか今ならconstexprにする
1002:はちみつ餃子
26/01/29 14:39:03.95 hMM3WHI30.net
>>994
>staticをつけるか
デフォルトで内部リンケージなんだってば。
static をつけてもつけなくても同じ。
Cでは外部リンケージなのでよく混同される。
1003:デフォルトの名無しさん
26/01/29 14:42:35.60 7sXa6UKh0.net
>>995
そうだね
訂正
しかし俺はつけるけど
1004:はちみつ餃子
26/01/29 14:44:24.78 hMM3WHI30.net
Cとの共存を考えて付ける習慣にしてる人は実際けっこういるっぽい。
1005:デフォルトの名無しさん
26/01/29 14:45:44.59 YJ+F37lYM.net
>>995
ということは、単なるマクロではなく、static int g_a = 5;
の時と同じように、複数の obj に、同名の変数領域が
確保されてしまう場合が有るという事なのかいな。
100 個のモジュールをリンクした場合、100 個の変数領域が
含まれてしまうと?
1006:デフォルトの名無しさん
26/01/29 14:47:10.08 YJ+F37lYM.net
内部リンケージではなく、COMDAT ANY section かも知れないぞ。
1007:はちみつ餃子
26/01/29 15:00:54.93 hMM3WHI30.net
>>998
言語の理屈とその実装は別のレイヤなので混同してはいけない。
変数の場所 (アドレス) を使ってないなら最適化で消えてもかまわない。
もちろん素直に場所を確保しても構わない。
1008:はちみつ餃子
26/01/29 15:14:33.52 hMM3WHI30.net
1000get
1009:1001
Over 1000 Thread.net
このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 278日 4時間 39分 36秒
1010:過去ログ ★
[過去ログ]
■ このスレッドは過去ログ倉庫に格納されています