- PR -

intは何でできてるの?

投稿者投稿内容
NothingBut.NETFX
大ベテラン
会議室デビュー日: 2001/09/13
投稿数: 102
投稿日時: 2002-05-24 19:50
引用:

autumunさん>
特にCTSに矛盾する主張をC#言語仕様は述べておらず、一見矛盾があるかのように見えるのは、日本語訳の問題と解釈します。


↓これのことですよね?

引用:

4.1.3 Simple types
C# provides a set of predefined struct types called the simple types. The simple types are identified through reserved words, but these reserved words are simply aliases for predefined struct types in the System namespace, as described in the table below.


どう読んでも日本語訳どおりにしか読めません。intはSystem.Int32のエイリアスです

引用:

すえぞうさん>
...
のようなコードをコンパイル、実行できるのでしょうか?


はっきり言います。コンパイルできません。C#言語仕様に、intはSystem.Int32のエイリアスだと書いてある以上、System.Int32を提供しないシステム上にC#言語を実装することはできません。C#コンパイラがintに出くわしたときにどんなコードを吐き出せばいいのか、そのルールがないからです。もしこれがコンパイルできるなら、それはC#ではありません。
Muse
常連さん
会議室デビュー日: 2002/03/08
投稿数: 34
投稿日時: 2002-05-25 00:15
引用:

objectさんの書き込み (2002-05-24 19:41) より:

だから、C#によって、「int」が「System.Int32」にC#の機能として「マッピング」されると考えた方が良いのではないでしょうか?


引用:

NothingBut.NETFXさんの書き込み (2002-05-24 19:50) より:

C#コンパイラがintに出くわしたときにどんなコードを吐き出せばいいのか、そのルールがないからです。もしこれがコンパイルできるなら、それはC#ではありません。


確かにそうですね さっきわたしが記事を投稿した後に、NothingBut.NETFXさんの「C#には型システムは存在しない」という言葉を思い出しました。もし、System name spaceの中にInt32が存在しなかったら、C#の文法にあるintというのは「キーワード」としては存在するけれど、型としては機能しないということに気がつきました。また、intというキーワードがSystem.Int32のエイリアスというのは、C#のコンパイラが「ソースにintが来たらSystem.Int32にする」という固定のルールがあって、別にtypedefのような文で定義しなおしてはいないとこうことも分かりました。
intの謎を解く鍵は、
引用:

「C#には型システムがない。あるのは共通型システム(CTS)であり、これはC#ではなくCLRの範疇に属する。C#には文法はあるが型システムはない。」


ですね
ところで更にお聞きしたいのですが、int32.csの
引用:

namespace System {
(中略)
public struct Int32 : IComparable, IFormattable, IConvertible
{
internal int m_value;


がどのような手順でコンパイルされるのか教えてもらえますか?
object
ぬし
会議室デビュー日: 2002/03/20
投稿数: 338
お住まい・勤務地: 香川県高松市
投稿日時: 2002-05-25 00:48
引用:

ところで更にお聞きしたいのですが、int32.csの
引用:

namespace System {
(中略)
public struct Int32 : IComparable, IFormattable, IConvertible
{
internal int m_value;


がどのような手順でコンパイルされるのか教えてもらえますか?



すえぞうさん、私が言いたかった事が十分伝わって無いように感じたので、補足します。

私は、上の例をみても分かる通り、「Int32」は「int」で定義されていると考えています。
何故この様な定義が必要なのでしょうか?
私は、つまりこの時点では、「Int32」は存在しないからこそ、「int」で定義していると考えます。

前にも書きましたが、「Int32」を実装しているC#と、「Frame Work」上のC#を同じC#とは考えない方が良いのじゃないでしょうか?
私は、そう考えています。
NothingBut.NETFX
大ベテラン
会議室デビュー日: 2001/09/13
投稿数: 102
投稿日時: 2002-05-25 11:55
引用:

すえぞうさんの書き込み (2002-05-25 00:15) より:
...
がどのような手順でコンパイルされるのか教えてもらえますか?


えっと、もちろん私はC#コンパイラの実装者ではありませんのでホントのところはわかりません。以下は想像(とILDASMの出力)に過ぎません、念のため。

コード:
	struct S {
		string s;
	}
	struct T {
		int i;
		S s;
	}


上記の型をコンパイルすると、C#コンパイラは次のようなCILコードを出力します。

コード:
	.class public sequential ansi sealed beforefieldinit S
		extends [mscorlib]System.ValueType
	{
		.field public string s
	}
	.class public sequential ansi sealed beforefieldinit T
		extends [mscorlib]System.ValueType
	{
		.field public int32 i
		.field public valuetype S s
	}


さらに、これらを利用する次のようなC#コードをC#コンパイラでコンパイルすると、

コード:
	S s; T t;
	s.s = "hello";
	t.i = 0;
	t.s = s;


次のようなCILコードが出力されます。

コード:
	.locals init (valuetype S s , valuetype T t)
	ldloca.s   s
	ldstr      "hello"
	stfld      string S::s
	ldloca.s   t
	ldc.i4.0
	stfld      int32 T::i
	ldloca.s   t
	ldloc.0
	stfld      valuetype S T::s
	ret


文字列や整数を扱うコードと、構造体を扱うコードの違いに注目してください。前者はstringやint32などの、ilasmアセンブリ言語の型の値を扱っているのに対して、後者はvaluetype Sという形でメタデータへの参照を行っています。これが、CLRが型についての情報を知っているか知らないかの違いです。

intがSystem.Int32のエイリアスであるという事実は、そこで止まってしまっては理解できないのです。さらに、System.Int32のボックス化されていない形式が、CLRが内部的に持っているint32という型にマップされるという事実まで踏み込まなければなりません。

さらに言うと、値型にはボックス化形式とボックス化されていない形式があることも理解しなければなりません。値型を宣言すると、その「値」の部分、つまりフィールド部分だけがスタック上に確保されるようなイメージになります。System.Int32のフィールドはm_valueだけですから、System.Int32を確保しようとすると、スタック上にm_valueの領域を確保しようとします。ここでもしm_valueの型(System.Int32==int32)の情報をCLRが知らなければ、CLRはメタデータを見て必要なサイズを知ります。ですが、この場合はCLRはサイズを知っていますから、問題なくスタック上に32ビットの領域を確保して、それを0で初期化することができるのです。
autumn
大ベテラン
会議室デビュー日: 2001/07/27
投稿数: 215
投稿日時: 2002-05-25 15:03
引用:

私は、上の例をみても分かる通り、「Int32」は「int」で定義されていると考えています。


 ソースコードを素直に読めば、そういう読みとれますね。
 余談ですが、
コード:
public void byint()
{
    int i=0;
    Console.WriteLine(i.ToString());
}
public void bystruct()
{
    System.Int32 i=0;
    Console.WriteLine(i.ToString());
}


 はどちらも、まったく同じアセンブラコードを吐き出します。
 そのことから考えると、おそらくC#コンパイラはintとSystem.Int32が等価であることを知っていて、処理に区別をしていないと思います。それに対して、アセンブラレベルでのint32とSystem.Int32は異なる役割を持っていて、使い分けられているように見えます。たとえばi=0ならint32だけで処理できますが、ToString()メソッドを呼ぶと、System.Int32を参照するコードが生成されます。
 ですので、根拠はありませんが、以下のような状況なのかもしれません。
・ C#コンパイラは、intとSystem.Int32が等価であることを知っている
・ C#コンパイラは、intとSystem.Int32が32bit符号付き整数であることを知っている
・ C#コンパイラは、System.Int32の構造体定義(どんなメソッドがある等)は知らない
・ C#コンパイラは、どちらの型もアセンブラのint32で扱おうとする
・ C#コンパイラは、int32で扱えない状況に出会ったら構造体定義を参照する
 すると、System.Int32の定義が存在しない状況でも、System.Int32の構造体定義を参照しない限り、intはコンパイル可能となります。
 また、C#コンパイラは、intとSystem.Int32が等価であることを知っているだけで、System.Int32の定義を内部に持っているわけではないので、C#コンパイラ外部でSystem.Int32を定義しても二重定義になりません。
 繰り返しますが、これが本当かどうかは知りませんよ。

引用:

前にも書きましたが、「Int32」を実装しているC#と、「Frame Work」上のC#を同じC#とは考えない方が良いのじゃないでしょうか?


 そう思います。
 言語仕様で要求されるライブラリをビルドするのに、それ自身の処理系を使う場合がありますが、当然その段階では、言語仕様を満たしていない状態で走ることになります。
arton
会議室デビュー日: 2002/03/22
投稿数: 19
投稿日時: 2002-05-27 01:33
全く唐突で、なにやらわからないと思いますが、autumnさん、NothingBut.NETFXさん、解説ありがとうございました。おかげで、間違いを修正できました(ちょっと遅きに失したけど)。


[ メッセージ編集済み 編集者: arton 編集日時 2002-05-27 01:45 ]
Muse
常連さん
会議室デビュー日: 2002/03/08
投稿数: 34
投稿日時: 2002-05-27 10:59
大変、興味深い解説、ありがとうございます。
ちょっと話が戻りますが、
引用:

NothingBut.NETFXさんの書き込み (2002-05-24 19:50) より:

はっきり言います。コンパイルできません。C#言語仕様に、intはSystem.Int32のエイリアスだと書いてある以上、System.Int32を提供しないシステム上にC#言語を実装することはできません。C#コンパイラがintに出くわしたときにどんなコードを吐き出せばいいのか、そのルールがないからです。もしこれがコンパイルできるなら、それはC#ではありません。


int32.csをコンパイルする時点では、C#という言語は仕様は満たしてはいないけれども、コンパイルは可能ということですね。ということは、System.Int32が、もし、実装されていない場合、

int i;
i = 0;

をコンパイルすると、コンパイラは「int」をILの「int32」にコンパイルするということでしょうか? autumnさんのいう通り、「int==System.int32」というように等価と考えれば、そうなると思います。
ということは、わたしが今まで考えていた、

C#の「int」キーワード → CLRの「System.Int32」にマッピング → ILの「int32」を出力

ではなく、

C#の「int」キーワード → ILの「int32」を出力
CLRの「System.Int32」 → ILの「int32」を出力

ということになると思います。この考えは正しいですか?
C#のコンパイラと.NET Frameworkのコンパイラが同じものだとは限らないということは、承知しているのですが・・・どうなんでしょね〜、気になります。

#何かあったのですか? (^^; > artonさん

#このスマイリーって書き方悪いですか?アイコンに変換されません → (^^;
object
ぬし
会議室デビュー日: 2002/03/20
投稿数: 338
お住まい・勤務地: 香川県高松市
投稿日時: 2002-05-27 12:00
引用:

すえぞうさんの書き込み (2002-05-27 10:59) より:
int32.csをコンパイルする時点では、C#という言語は仕様は満たしてはいないけれども、コンパイルは可能ということですね。ということは、System.Int32が、もし、実装されていない場合、

int i;
i = 0;

をコンパイルすると、コンパイラは「int」をILの「int32」にコンパイルするということでしょうか? autumnさんのいう通り、「int==System.int32」というように等価と考えれば、そうなると思います。
ということは、わたしが今まで考えていた、

C#の「int」キーワード → CLRの「System.Int32」にマッピング → ILの「int32」を出力

ではなく、

C#の「int」キーワード → ILの「int32」を出力
CLRの「System.Int32」 → ILの「int32」を出力

ということになると思います。この考えは正しいですか?
C#のコンパイラと.NET Frameworkのコンパイラが同じものだとは限らないということは、承知しているのですが・・・どうなんでしょね〜、気になります。


すえぞうさん、autumn、NothingBut.NETFX御二人それぞれ、C#の「内部処理」に関するとてもデリーケートな話をしてた訳ですよ!
内部処理という事をもっと理解すべきだと思います。

大切な事ですが、
「int」=「System.Int32」
これは、基本的です。

ただ、内部的に問題が無い限り、C#が「int」を「Integer」として処理しているという事だと思います。
それで、全てを理解すべきだと思います。
(「int」はC#にとってプリミティブなんです!)

それから、
引用:

System name spaceにもしも、Int32というタイプが存在しなかったら、このような場合であっても、C#のプログラムは依然として、
コード:
int i; 
i = 0; 


のようなコードをコンパイル、実行できるのでしょうか?


ですが、autumnさん、NothingBut.NETFXさんそれぞれ異なる見解ですが、これは仕様の問題です!
C#の本来の仕様からいけば、これは出来ないと思います。(C#はInt32の存在が前提ですから!)
でも、技術者は、基本的にはこれを処理出来るように作るでしょう!(間違いとする場合は、チェックしてハジクだけ!)
(「前提が誤ってる時、結果は正誤どちらも場合も正しい。」:これは、記号論理的には正です!)

スキルアップ/キャリアアップ(JOB@IT)