This document, which is part of the C# language spec, says that the behavior of fixed
in C# is implementation-defined if it is used on a null/empty array reference. To quote it:
An expression of an array-type with elements of an unmanaged type T, provided the type T* is implicitly convertible to the pointer type given in the fixed statement. In this case, the initializer computes the address of the first element in the array, and the entire array is guaranteed to remain at a fixed address for the duration of the fixed statement. The behavior of the fixed statement is implementation-defined if the array expression is null or if the array has zero elements.
However, it does not make the same claim for empty strings, only saying that the behavior isn't defined if the string is null. Here's the next paragraph detailing how it works for strings:
An expression of type string, provided the type char* is implicitly convertible to the pointer type given in the fixed statement. In this case, the initializer computes the address of the first character in the string, and the entire string is guaranteed to remain at a fixed address for the duration of the fixed statement. The behavior of the fixed statement is implementation-defined if the string expression is null.
So if I'm reading this correctly, this means that the behavior IS defined for empty strings, right? What happens, then, if you do something like
fixed (char* pch = string.Empty)
{
Console.WriteLine((int)*pch);
}
? Is it guaranteed to print out 0, since strings in .NET are null-terminated? Do all ECMA 335 implementations (e.g. Microsoft's CLR, Mono) require strings to be null-terminated?
Thanks.
Yes, it's guaranteed to print out 0 due to a later bit of 18.6:
A
char*
value produced by fixing a string instance always points to a null-terminated string. Within a fixed statement that obtains a pointer p to a string instance s, the pointer values ranging fromp
top + s.Length - 1
represent addresses of the characters in the string, and the pointer valuep + s.Length
always points to a null character (the character with value '\0').
I can't say I've tried this on Mono, but it would definitely be a non-compliance issue if that were the case. The same text occurs in the ECMA standard as in the MS specification. (Clause 27.6 in the C# 2 edition; it looks like it'll be 24.7 in the C# 5 edition.)
See more on this question at Stackoverflow