Reputation: 1895
I am playing around with the Marshal class in C# and am slightly confused by the result of this operation:
string someVal = "Hello There";
IntPtr ptS = Marshal.StringToHGlobalAnsi(someVal);
char* ptsPt = (char*)ptS.ToPointer();
After looking at ptsPt[0] in the immediate window it contains this value: '效'
I am guessing it has something to do with the StringToHGlobalAnsi
Method treating the managed chars as 8 bit values, but when they really they are 16 bit. But I cannot quite understand why this is happening.
I know I can get around this issue by changing it to StringToHGlobalUni
. But I don't understand why this is!
Cheers
Upvotes: 4
Views: 3499
Reputation: 61402
It's because in C#, char
is a 16-bit wide type. StringToHGlobalAnsi
converts the string to ANSI, that is 1 byte per character. Then you look at ptsPt[0]
, which is interpreted to contain both of the first two ANSI characters.
Here's what the original string look like in memory:
00 48 00 65 00 6C 00 6C 00 6F 00 20 ...
This is because C# strings are stored in UTF-16, and the above is UTF-16 for "Hello There".
After the call to StringToHGlobalAnsi
, a new piece of memory is allocated, containing these bytes:
48 65 6C 6C 6F 20 ...
(and incidentally, this means you should free it with Marshal.FreeHGlobal
when you're done).
Then, when you get a char*
to this, the first char
pointed to comprises the bytes 48 65
, which due to little endianness really means 0x6548
, which stands for the character 效.
Upvotes: 5