8

これは奇妙に思えるかもしれませんが、C では (size_t)(void*)0 == 0 は言語仕様によって保証されていません。コンパイラは、null に任意の値を使用できます (ほとんどの場合、0 を使用しますが)。

C# では、アンセーフ コードで null または (T*)0 をポインターに割り当てることができます。

  1. 違いはありますか?
  2. (long)(void*)0 == 0 (保証されているかどうか? 別の言い方をすると: IntPtr.Zero.ToInt64() == 0)

MSDN は、IntPtr.Zero について次のように述べています。

「このフィールドの値はヌルと同等ではありません。」C コードとの互換性を維持したい場合、それは非常に理にかなっています。C ヌル ポインターに変換されなければ、相互運用性には意味がありません。しかし、IntPtr.Zero.ToInt64() == 0 が内部的に IntPtr.Zero である場合でも、可能な場合があるかどうかを知りたいです (CLR は、キャスト操作で null を 0 に変換する場合としない場合があります)。

この質問の複製ではありません

4

2 に答える 2

5

この問題を回避できます。

char* foo = (char*)(void*)0;
char* bar = default(char*); // <======= the one to look at
Console.WriteLine(foo == bar); // writes True

したがって、それらは同じですが、使用するdefaultことで、コードに仮定や厄介なキャストを埋め込む必要がなくなります。上記を逆アセンブルすると、唯一の違いは符号付き/符号なしです-どちらも4バイト定数(i4/ )で始まり、native-int( / )u4にキャストされます(コメントは私のものです):iu//

.maxstack 2
.locals init (
    [0] char* foo,
    [1] char* bar)
L_0000: ldc.i4.0 // (char*)(void*)0;
L_0001: conv.i 
L_0002: stloc.0 // foo=
L_0003: ldc.i4.0 // default(char*);
L_0004: conv.u 
L_0005: stloc.1 // bar=
L_0006: ldloc.0 
L_0007: ldloc.1 
L_0008: ceq  // foo == bar
L_000a: call void [mscorlib]System.Console::WriteLine(bool)
于 2010-05-05T04:27:48.787 に答える
0

Cでは、NULLアーキテクチャ固有として定義されています。ほとんどのアーキテクチャは0を使用しますが、使用しないアーキテクチャもあります。NULL == 0したがって、 Cではそれを想定することはできません。

NULLC#でどのように機能するかはよくわかりませんが、0にキャストするのではなく、C#で指定する標準的な方法を使用することをお勧めします。

于 2010-05-05T01:05:58.237 に答える