William
William

Reputation: 1895

Marshaling managed string to char pointer c#

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 StringToHGlobalAnsiMethod 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

Answers (1)

Roman Starkov
Roman Starkov

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

Related Questions