Is there any difference between null and 0 when assigning to pointers in unsafe code?
This 开发者_如何学JAVAmay seem odd, but in C (size_t)(void*)0 == 0 is not guaranteed by the language spec. Compilers are allowed to use any value they want for null (although they almost always use 0.)
In C#, you can assign null or (T*)0 to a pointer in unsafe code.
- Is there any difference?
- (long)(void*)0 == 0 (guaranteed or not? put another way: IntPtr.Zero.ToInt64() == 0)
MSDN has this to say about IntPtr.Zero:
"The value of this field is not equivalent to null." Well if you want to be compatible with C code, that makes a lot of sense - it'd be worthless for interop if it didn't convert to a C null pointer. But I want to know if IntPtr.Zero.ToInt64() == 0 which may be possible, even if internally IntPtr.Zero is some other value (the CLR may or may not convert null to 0 in the cast operation)
Not a duplicate of this question
You could avoid the issue:
char* foo = (char*)(void*)0;
char* bar = default(char*); // <======= the one to look at
Console.WriteLine(foo == bar); // writes True
So they are the same, but using default
avoids having to embed any assumption or nasty casts into the code. Disassembling the above, the only difference is signed / unsigned - both start with a 4-byte constant (i4
/ u4
) then cast to native-int (i
/ u
) (the //
comments are mine) :
.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)
In C, NULL
is defined as architecture specific. While most architectures use 0, some don't. So, you cannot assume that NULL == 0
in C.
Not quite sure how it works in C# though I would recommend that you stick to the standard way of specifying NULL
in C# instead of casting it to 0.
精彩评论