C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

C# 定数テーブル /774RR (18/11/02(Fri) 11:04) #89151
Re[1]: C# 定数テーブル /にゃるら (18/11/02(Fri) 12:33) #89154
  └ Re[2]: C# 定数テーブル /774RR (18/11/02(Fri) 14:43) #89156
    └ Re[3]: C# 定数テーブル /????? (18/11/02(Fri) 15:04) #89157
      └ Re[4]: C# 定数テーブル /にゃるら (18/11/02(Fri) 15:05) #89158
        └ Re[5]: C# 定数テーブル /774RR (18/11/02(Fri) 16:00) #89161
          └ Re[6]: C# 定数テーブル /にゃるら (18/11/05(Mon) 12:27) #89180


親記事 / ▼[ 89154 ]
■89151 / 親階層)  C# 定数テーブル
□投稿者/ 774RR (641回)-(2018/11/02(Fri) 11:04:23)

分類:[C#] 

C でいう定数テーブルを C# で作りたいんですが、どう書くと一番効率よくて安全ですかね?

C ソース
uint16_t const crc16usb[] = {
    0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E ...
};

要するにコンパイル時に値が決定済みな静的定数テーブルを唯一つだけ定数領域に置いてプログラムと同じ寿命を持たせる、つまり gc 対象にしたくないわけなのですが C# の配列は参照型で new しないと作れないので gc 対象になるのがどうも気に入りません。
readonly UInt16[] crc16usb = new UInt16[] { ... };
をクラスメンバに置くのは効率悪いと思うし readonly を const にするとコンパイル通らないし。

[ □ Tree ] 返信 編集キー/

▲[ 89151 ] / ▼[ 89156 ]
■89154 / 1階層)  Re[1]: C# 定数テーブル
□投稿者/ にゃるら (44回)-(2018/11/02(Fri) 12:33:26)
2018/11/02(Fri) 12:55:27 編集(投稿者)

No89151 (774RR さん) に返信

> readonly UInt16[] crc16usb = new UInt16[] { ... };
> をクラスメンバに置くのは効率悪いと思うし readonly を const にするとコンパイル通らないし。

インスタンスメンバであればインスタンス数分になるので効率悪いと思ったのですけど、
クラスメンバであれば一回しか作られないので、それほど効率悪くないかなって。

static readonly UInt16[] crc16usb = new UInt16[] { ... };

[ 親 89151 / □ Tree ] 返信 編集キー/

▲[ 89154 ] / ▼[ 89157 ]
■89156 / 2階層)  Re[2]: C# 定数テーブル
□投稿者/ 774RR (642回)-(2018/11/02(Fri) 14:43:49)
現状 static readonly UInt16[] crc16table = {...}; として実用上の問題はないのですが
根っからの native C/C++er としては初期値一覧と実際に使われる配列が別領域に配置されるか否かが
微妙にというかとても気になります。今の時点で IL 読んでる暇がないっす。

C# で最初にハマったのが const
C# の const って真に const なので C++ でいう static const なのね。驚き。
[ 親 89151 / □ Tree ] 返信 編集キー/

▲[ 89156 ] / ▼[ 89158 ]
■89157 / 3階層)  Re[3]: C# 定数テーブル
□投稿者/ ????? (4回)-(2018/11/02(Fri) 15:04:40)
No89156 (774RR さん) に返信
> 現状 static readonly UInt16[] crc16table = {...}; として実用上の問題はないのですが
> 根っからの native C/C++er としては初期値一覧と実際に使われる配列が別領域に配置されるか否かが
> 微妙にというかとても気になります。今の時点で IL 読んでる暇がないっす。
> 
> C# で最初にハマったのが const
> C# の const って真に const なので C++ でいう static const なのね。驚き。

C++勉強不足なので、質問したいのですけど。
C#だとたとえば、

ClassLibrary1.dll
    public class Class1
    {
        public const int NConst = 10000;
    }
 
App.exe
    /// <summary>
    /// コンソールアプリ
    /// </summary>
    static class Program
    {
        static void Main()
        {
            Console.WriteLine(ClassLibrary1.Class1.NConst);
        }
    }

としていったんビルドし、そのあとApp.exeを別の場所においておいてDllの方のNConstを1にしてビルドして、
別の場所のApp.exeのところにDllを持っていって動かすと、変更後の「1」ではなく「10000」が出ます。

このような動きになる定数がc++のstatic constっていうのでしょうか?

[ 親 89151 / □ Tree ] 返信 編集キー/

▲[ 89157 ] / ▼[ 89161 ]
■89158 / 4階層)  Re[4]: C# 定数テーブル
□投稿者/ にゃるら (45回)-(2018/11/02(Fri) 15:05:09)
No89157 (????? さん) に返信

名前入れ忘れました。すみません。。
[ 親 89151 / □ Tree ] 返信 編集キー/

▲[ 89158 ] / ▼[ 89180 ]
■89161 / 5階層)  Re[5]: C# 定数テーブル
□投稿者/ 774RR (643回)-(2018/11/02(Fri) 16:00:55)
いや C++ の static const はコンパイル時に命令語に展開されることを期待するものです。

static const int myconst = 3;
int func() { return myconst; }
なる関数を作ったら機械語で "MOV.L #3, R1" になることをプログラマは期待します。
機械語レベルでイミディエイトになれば「変数」を参照する必要がないわけで、
リンク時最適化により myconst なる変数は消去されることすら期待されています。
(それを究極まで進めたのが constexpr )

C# で static const int MySize = 4; と書いたら怒られたのが衝撃的でした。


[ 親 89151 / □ Tree ] 返信 編集キー/

▲[ 89161 ] / 返信無し
■89180 / 6階層)  Re[6]: C# 定数テーブル
□投稿者/ にゃるら (46回)-(2018/11/05(Mon) 12:27:41)
No89161 (774RR さん) に返信
> 機械語レベルでイミディエイトになれば「変数」を参照する必要がないわけで、
> リンク時最適化により myconst なる変数は消去されることすら期待されています。

そういったことまで含めた「安全」というところまでは私は普段意識しないので感覚的に理解できていませんでした。
コーディングで「定数」として扱われるというレベルでの安全性しか考慮したことがないもので。

# dumpbinでstatic constがMov命令のオペランドに実値で埋め込まれるのを確認しました。

本来の「質問」ではないのに逆質問をすることになってしまい、すみませんでした。





[ 親 89151 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -