It's in section 18.6 of the spec - the fixed statement.
The relevant productions are:
fixed-statement:
fixed ( pointer-type fixed-pointer-declarators ) embedded-statement
fixed-pointer-declarator:
identifier = fixed-pointer-initializer
fixed-pointer-initializer:
& variable-reference
expression
You're trying to use the expression version. Now, while there isn't a normal "conversion as an expression* from string to char *, the spec calls out the string case, saying that a fixed-pointer-initializer can be:
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 although it looks like you're just performing a normal variable declaration and using an implicit conversion from string to char *, you're really making use of a special case of what the expression in a fixed-pointer-initializer is allowed to be.
stringobject and gives you the pointer to its first char instead (it also does so for arrays). Special cases in the runtime ;-)string.GetHashCode()which is different in different versions of BCL and also different in Mono. In some implementation non zeroRuntimeHelpers.OffsetToStringDatais added to the pointer value before processing. This could mean that whether or not it points to the first character is version dependent.OffsetToStringDatamyself a first (even though it makes sense), but if that's version-dependent it's... scary.OffsetToStringDatais added but it always seems to amount to zero. I wonder why. On an unrelated topic if you run GetHashCode on the same string in .net 2.0 .net 4.0 and mono you will get 3 different results. Starting from .net 4.5 you also haveUseRandomizedStringHashingfrom app.config that affects how it's calculated once again.