我在SO和其他论坛上看过几个相关的主题,但是我的问题没有找到可行的答案。
这是我的代码:
[StructLayout(LayoutKind.Explicit, Size = 128)]
internal unsafe struct Frame
{
[FieldOffset(0)]
public fixed byte Bytes[128];
[FieldOffset(0)]
public long Low;
[FieldOffset(128 - sizeof(long))]
public long High;
}
unsafe private void button32_Click(object sender, EventArgs e)
{
Frame frame;
// ERROR: Error 15 You cannot use the fixed statement to take the address of an already fixed expression
fixed (byte* ptr = frame.Bytes)
{
}
// ERROR
Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes, 0, 128));
frame.Low = 1234;
//Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes));
frame.High = 5678;
//Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes));
}
答案 0 :(得分:2)
static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
static string GetString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
static byte[] StringToByteArray(string str, int length)
{
return Encoding.ASCII.GetBytes(str.PadRight(length, ' '));
}
答案 1 :(得分:1)
我明白了。刚刚将struct包装到另一个类中以消除固定指针问题。这将在新类的内存框架内创建结构。然后将固定数组转换为byte []以消除GetString()问题。也许这有帮助吗?
namespace test
{
[StructLayout(LayoutKind.Explicit, Size = 128)]
internal unsafe struct Frame
{
[FieldOffset(0)]
public fixed byte Bytes[128];
[FieldOffset(0)]
public long Low;
[FieldOffset(128 - sizeof(long))]
public long High;
}
internal class NewClass
{
public Frame FixedBytesArray;
}
internal class Program
{
static void Main(string[] args)
{
unsafe
{
NewClass NewType = new NewClass();
NewType.FixedBytesArray.High = 12345;
NewType.FixedBytesArray.Low = 6789;
// ERROR: Error 15 You cannot use the fixed statement to take the address of an already fixed expression
fixed (byte* ptr = NewType.FixedBytesArray.Bytes)
{
byte[] bytes = new byte[128];
int index = 0;
for (byte* counter = ptr; *counter != 0; counter++)
{
bytes[index++] = *counter;
}
// ERROR
Console.Write(System.Text.Encoding.ASCII.GetString(bytes, 0, 128));
//frame.Low = 1234;
//Console.Write(System.Text.Encoding.ASCII.GetString(frame.Low));
//frame.High = 5678;
//Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes));
}
}
}
}
}
答案 2 :(得分:0)
编译器错误很好地说明了这一点:你试图修复已经修复过的东西......
您只在分配指针时修复引用。这可以防止将引用移动到内存中的其他位置(垃圾收集)然后预期 - 使用MS字,引用变为“固定”。
在你的情况下,你不需要在定义时修改你的结构,但是当引用你的指针时通过应用“fixed”语句来修复'source'(这部分代码是正确的)。
解决方案应该是从结构中删除fix语句。 如果您想阅读一些有关它的内容:MSDN - fixed Statement (C# Reference)
答案 3 :(得分:0)
以上内容对我无用,因此我创建了另一个解决方案:
StringBuilder sb = new StringBuilder();
fixed (byte* b = fixedByteArray)
{
for (int i = 0; i < knownLengthOfByteArray; i++)
{
sb.Append((char)b[i]);
}
}
return sb.ToString();
适用于ANSI字符串。