如果高手路过,请帮忙解决下
想要实现一个具有固定大小的结构体,如下所示:
struct Info
{
public char name[16];
public char cipher[16];
public char signature[256];
}
(1) 测试一
用fixed关键字和Mashal类来实现
1>结构的声明
在C#中,数组是引用对象,属于托管对象;而我要实现的则是非托管对象,为防止分配的内存被垃圾回收机制回收掉,所以用fixed关键字来盯住
声明如下:
unsafe struct Info
{
public fixed char name[16];
public fixed char cipher[16];
public fixed char signature[256];
}
2>结构的赋值
char name[16]在C#中认为是一个char* ,即字符指针,属于非托管对象;string属于托管对象;两者之间相互转换需要用到Marshal类的方法进行转换
char* pName=myInfo.name;
pName=(char* )Marshal.StringToBSTR("abcd");
问题就出在: char* pName=myInfo.name;
问题:调试的时候发现,pName是有值的,而myInfo.name仍然非空。
原因:两者并未指向同一内存区域
解决办法:尚未知
(2) 测试二
用MarshalAsAttribute类与MarshalAs来实现托管对象对非托管对象的模拟
这个方法不用在unsafe环境中编译
[MarshalAs()]可以实现一个MarshalAsAttribute类的对象
用法:[MarshalAs(UnmanagedType, 命名参数)]
当需要实现固定大小的字符数组时,UnmanagedType 设置为 ByValArray时,并设置 SizeConst 以指示数组中的元素数;
代码如下:
struct Info
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public char[] name;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public char[] cipher;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
public char[] signature;
}
使用的时候也可以按正常的char[]使用
Info myInfo;
string name = "abcd";
myInfo.name = name.ToCharArray();
string cipher = "1234";
myInfo.cipher=cipher.ToCharArray();
string signature = "it is a new test";
myInfo.signature = signature.ToCharArray();
注意:在上述赋值语句中,myInfo.name 等的大小是string name的大小,即其大小不足16,导致了如下问题:
因为我有一个特殊的需要,把该结构体转为byte[]型,出了点问题。提示如下错误:嵌入数组实例的长度与布局中声明的长度不匹配。
改进
字符串string有一个方法PadLeft()/PadRight(),这两个方法能够将字符串填充为固定大小的字符串
函数如下:
PadRight(Int32) 左对齐此字符串中的字符,在右边用空格填充以达到指定的总长度。
PadRight(Int32, Char) 左对齐此字符串中的字符,在右边用指定的 Unicode 字符填充以达到指定的总长度。
注意:该方法可以返回一个新的string,而不会改变调用该方法的string
改进之后的赋值如下:
Info myInfo;
string name = "abcd";
myInfo.name = name.PadRight(16).ToCharArray();
string cipher = "1001593";
myInfo.cipher=cipher.PadRight(16).ToCharArray();
string signature = "it is a new test";
myInfo.signature =signature.PadRight(256).ToCharArray() ;
这次再进行结构与byte[]的转换就没有问题了,成功!
引申
同样的,用string的方法copyto()也应该可以,没有做实验