以前C++的代码,想移到C#上,请问在C#中怎么实现如下struct:
//C++ code
struct _cmdTag
{
unsigned char cmd:4;
unsigned char cmd_type:3;
unsigned char active:1;
};vod SetCmdFrame(unsigned char* pBuf, unsigned char cmd, unsigned char cmd_type)
{
_cmdTag *pFrame = (_cmdTag*)pBuf;
pFrame->cmd = cmd;
pFrame->cmd_type = cmd_type;
pFrame->active = 0; //主动或被动
...
}void IsCmdFrame(unsigned char* pBuf)
{
_cmdTag *pFrame = (_cmdTag*)pBuf;
if(pFrame->cmd == CMD_SEND_DATA)
{
...
}
...
}请问C#如何实现以上代码啊?
//C++ code
struct _cmdTag
{
unsigned char cmd:4;
unsigned char cmd_type:3;
unsigned char active:1;
};vod SetCmdFrame(unsigned char* pBuf, unsigned char cmd, unsigned char cmd_type)
{
_cmdTag *pFrame = (_cmdTag*)pBuf;
pFrame->cmd = cmd;
pFrame->cmd_type = cmd_type;
pFrame->active = 0; //主动或被动
...
}void IsCmdFrame(unsigned char* pBuf)
{
_cmdTag *pFrame = (_cmdTag*)pBuf;
if(pFrame->cmd == CMD_SEND_DATA)
{
...
}
...
}请问C#如何实现以上代码啊?
char* string
传出的char* StringBuilder
short short
char byte
char[n] fixed byte[n]
http://topic.csdn.net/u/20110124/18/b5ff89bd-b488-4e7e-bf87-926ab6251968.html
{
byte cmd:4;
byte char cmd_type:3;
byte char active:1;
};unsafe void SetCmdFrame(byte* pBuf, byte cmd, byte cmd_type)
{
_cmdTag* pFrame = (_cmdTag*)pBuf;
pFrame->cmd = cmd;
pFrame->cmd_type = cmd_type;
pFrame->active = 0; //主动或被动
...
}unsafe void IsCmdFrame(byte* pBuf)
{
_cmdTag* pFrame = (_cmdTag*)pBuf;
if(pFrame->cmd == CMD_SEND_DATA)
{
...
}
...
}
Ok,删除以前的东西重新用C#编程,
那么C++实现的那个代码,
请问用C#如何实现?
谢谢!
Class _cmdTag
{
public byte cmd;
public byte cmd_type;
public byte active;
public static _cmdTag Convert(Byte[] b)
{
判断b
_cmdTag c = new _cmdTag();
c.cmd = b[0];
c.cmd_type = b[1];
c.active = b[2];
return c;
}
};void SetCmdFrame(byte[] pBuf, byte cmd, byte cmd_type)
{
_cmdTag pFrame = _cmdTag.Convert(pBuf);
pFrame.cmd = cmd;
pFrame.cmd_type = cmd_type;
pFrame.active = 0; //主动或被动
...
}void IsCmdFrame(byte[] pBuf)
{
_cmdTag pFrame = _cmdTag.Convert(pBuf);
if(pFrame.cmd == CMD_SEND_DATA)
{
...
}
...
}
//C++ code
struct _cmdTag
{
unsigned char cmd:4;
unsigned char cmd_type:3;
unsigned char active:1;
};
理解为:
struct _cmdTag
{
unsigned char cmd[4];
unsigned char cmd_type[3];
unsigned char active[1];
};
或者:
struct _cmdTag
{
unsigned char[4] cmd;
unsigned char[3] cmd_type;
unsigned char[1] active;
};请,先弄明白C++的“位域”,
谢谢!
竟然遇到大麻烦了,
老板让我们转到C#,
看来C#并不能完成C++所能完成的全部功能啊。
http://topic.csdn.net/t/20030531/22/1860471.html
能完成C++所有的功能吗?
晕,到底转向C#可以吗?
上面这个帖子牛,想到枚举
谢谢!那个帖子的问题与我这个问题有相似的地方,
但是它那是用C#的枚举解决问题,
但这是不行的,例如:
struct _cmdTag
{
unsigned int cmd:4;
unsigned int active:1;
unsigned int frame_len:27;
};
就没法解决,因为frame_len是表示27bit的整数值。
你那个结构用C#写成下面这样,浪费一点空间不就完了,active的类型也可以改成bool。移植程序嘛,灵活一点。要是什么都完全一样,就用不着移植了struct _cmdTag
{
unsigned char cmd;
unsigned char cmd_type;
unsigned char active;
};
朋友,你没有写过类似的东西,可能没法理解
例如
void compose(char* buffer)
{
//buffer 是需要out的数据帧 函数内组包 //ether头 结构体
ether_header* eh;
//arp头 结构体
arp_header* ah; eh = (etherheader*)buffer;
ah = (arp_header*)(buffer+sizeof(ether_header)) ; eh.dmac =...
...
ah.targetip = ... 这样,在数据帧的各部分结构体的数据赋值完毕之后,buffer也同时填充完毕了
也就是说,如果用了char,那么在buffer中就明显存在了问题,因为原来是1bit的数据你填充了8bit!!!
}这个问题要从内存角度去理解,个人在C#还没有发现可以达到这种目的的方法,当然可能是我才疏学浅
所以如果没什么好办法的话,用char或者其他类型作为结构体的成员类型,敷值完毕以后自己计算byte很傻,不过能做出来C#有自己的优势,不过底层的东西,还是C比较方便
不知道这样行不
class Program
{
static void Main(string[] args)
{
CmdTag ct = new CmdTag(25);
Console.WriteLine(string.Format("cmd:{0} cmdType:{1} active:{2}", ct["cmd"], ct["cmd_type"],ct["active"]));
ct["cmd"] = 3;
Console.WriteLine(string.Format("cmd:{0} cmdType:{1} active:{2}", ct["cmd"], ct["cmd_type"], ct["active"]));
ct["cmd_type"] = 6;
Console.WriteLine(string.Format("cmd:{0} cmdType:{1} active:{2}", ct["cmd"], ct["cmd_type"], ct["active"]));
ct["active"] = 1;
Console.WriteLine(string.Format("cmd:{0} cmdType:{1} active:{2}", ct["cmd"], ct["cmd_type"], ct["active"]));
CmdTag ct1 = (CmdTag)3; Console.WriteLine(string.Format("cmd:{0} cmdType:{1} active:{2}", ct1["cmd"], ct1["cmd_type"], ct1["active"]));
Console.ReadLine(); }
}
class CmdTag
{
private byte _v; //构造函数
public CmdTag() { }
public CmdTag(byte v)
{
_v = v;
} //强制运算符的重载,将byte转换为CmdTag类型
public static explicit operator CmdTag(byte b)
{
return new CmdTag(b);
} //索引器
public byte this[string str]
{
//获取字段值
get
{
if (str == "cmd") return (byte)(_v >> 4);
if (str == "cmd_type") return (byte)((_v & 0xf) >> 1);
if (str == "active") return (byte)(_v & 0x01);
throw new Exception(string.Format("不存在字段:{0}", str));
}
//设置字段值
set
{
if (str == "cmd") _v = (byte)((_v&0xf)|(value<<4));
else if (str == "cmd_type") _v =(byte)((_v&0xf1)|(value<<1));
else if (str == "active") _v = (byte)((_v&0xfe)|value);
else throw new Exception(string.Format("不存在字段:{0}",str));
}
}
}
else if (str == "cmd_type") _v = (byte)((_v & 0xf1) | ((value << 1) & 0xe));
else if (str == "active") _v = (byte)((_v&0xfe)|(value&0x1));
else throw new Exception(string.Format("不存在字段:{0}",str));
struct _cmdTag
{
public byte b;
public byte cmd()
{
return (byte)(((byte)(b << 4)) >> 4);
}
public byte cmd_type()
{
return (byte)(((byte)(b << 1)) >> 5);
}
public byte active()
{
return ((byte)(b >> 7));
}
}
unsafe static void Main(string[] args)
{
byte* f = stackalloc byte[10];
*f = 248;
_cmdTag* d = (_cmdTag*)f;
Console.WriteLine(d->cmd());
Console.WriteLine(d->cmd_type());
Console.WriteLine(d->active());
Console.ReadLine();
}
{
[global::System.AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
sealed class BitfieldLengthAttribute : Attribute
{
uint length; public BitfieldLengthAttribute(uint length)
{
this.length = length;
} public uint Length { get { return length; } }
} static class PrimitiveConversion
{
public static long ToLong<T>(T t) where T : struct
{
long r = 0;
int offset = 0; // For every field suitably attributed with a BitfieldLength
foreach (System.Reflection.FieldInfo f in t.GetType().GetFields())
{
object[] attrs = f.GetCustomAttributes(typeof(BitfieldLengthAttribute), false);
if (attrs.Length == 1)
{
uint fieldLength = ((BitfieldLengthAttribute)attrs[0]).Length; // Calculate a bitmask of the desired length
long mask = 0;
for (int i = 0; i < fieldLength; i++)
mask |= 1 << i; r |= ((UInt32)f.GetValue(t) & mask) << offset; offset += (int)fieldLength;
}
} return r;
}
} struct PESHeader
{
[BitfieldLength(2)]
public uint reserved;
[BitfieldLength(2)]
public uint scrambling_control;
[BitfieldLength(1)]
public uint priority;
[BitfieldLength(1)]
public uint data_alignment_indicator;
[BitfieldLength(1)]
public uint copyright;
[BitfieldLength(1)]
public uint original_or_copy;
}; public class MainClass
{
public static void Main(string[] args)
{
PESHeader p = new PESHeader(); p.reserved = 3;
p.scrambling_control = 2;
p.data_alignment_indicator = 1; long l = PrimitiveConversion.ToLong(p);
for (int i = 63; i >= 0; i--)
{
Console.Write( ((l & (1l << i)) > 0) ? "1" : "0");
} Console.WriteLine(); return;
}
}
}
你说得倒是好,
改下代码就行吗?
把所有设备的代码都改变吗?
那么请说服大家把TCP等等协议都改变吧!
问了个位域问题,
硬是让一帮人说C++故意执拗于性能,
故意钻牛角之类显示自己理论多高的样子,
说白了,做应用软件的人,
很难理解底层为什么要这么做,
真是不做一行,不懂一行啊,
希望那些没有做过底层的,
不要再以此来讥讽了,
做C++的并不是为显摆才让代码那样子,
我也知道了C#的局限,
所以转入C#也会深重考虑了。
c.cmd = b[0];
c.cmd_type = b[1];
c.active = b[2];
return c;
}
};
非托管 转 托管的时候并不一定要把代码全部重写,也可以试着将非托管的部分封装成dll,给托管代码调用
像bitfield 及 union等最好能通过接口封装掉,不是说C#不能调,而是降低调用的麻烦程度,凡事有个度,具体事情具体衡量。PS:某些人回答问题最好能看清楚别人问的问题是什么才回答,而不是一上来就否定人家,给出的建议也没什么建树,不知所云,不止在一个帖子里看到这样的回答,忍不住多嘴一句。
BitVector32.Section sectCmd = BitVector32.CreateSection(4);
BitVector32.Section sectCmdType = BitVector32.CreateSection(3, sectCmd);
BitVector32.Section sectActive = BitVector32.CreateSection(1, sectCmdType);cmd[sectCmd] = 2;
cmd[sectCmdType] = 1;代码没有测试过,随手敲的,希望对你有帮助。
对,您这话在理,
我从C++刚转到C#(老板让的),
对C#比较茫然(当然学得还是比较快的,看了一个星期的C#电子书),
只是对位域感到有些棘手,
迫切希望能得到有这方面经验的帮助,
希望回答问题前,确实要搞清楚别人在问什么,
这样对自己也是一次帮助。
在我们公司招聘人的时候,不会对人员长期使用的语言有严格的限制,因为是小公司。但不论C#程序员将原有程序改为C++,还是C++程序员将原有程序改为C#,不管有没有学过另一个语言,一个东西的移植都不会因为跨语言而卡壳。卡壳只会发生在语言层面之外的思路上。
也感谢您鼎力帮助,
确实,语言的东西,关键要看怎么用它,
我们公司老板看到C#做界面快,
也就希望我们用它,
其实底层的东西,
还是C/C++合适,
当然,仁者见仁智者见智了。
struct _cmdTag
{
unsigned char cmd:4;
unsigned char cmd_type:3;
unsigned char active:1;
};vod SetCmdFrame(unsigned char* pBuf, unsigned char cmd, unsigned char cmd_type)
{
_cmdTag *pFrame = (_cmdTag*)pBuf;
pFrame->cmd = cmd;
pFrame->cmd_type = cmd_type;
pFrame->active = 0; //主动或被动
...
}void IsCmdFrame(unsigned char* pBuf)
{
_cmdTag *pFrame = (_cmdTag*)pBuf;
if(pFrame->cmd == CMD_SEND_DATA)
{
...
}
...
}public struct _cmdTag
{
private byte data;
public byte cmd
{
get { return cmd & 15; }
set { data |= value; }
}
public byte cmd_type
{
get { return cmd >> 4 & 7; }
set { data |= value << 4; }
}
public byte active
{
get { return cmd >> 7; }
set { data |= value << 7; }
}
//直接赋值
public byte Data
{
get { return data; }
set { data = value; }
}
}
using System.Runtime.InteropServices; [StructLayout(LayoutKind.Explicit)]
public struct _cmdTag
{
[FieldOffset(0)]
public byte cmd;
[FieldOffset(4)]
public byte cmd_type;
[FieldOffset(7)]
public byte active;
}
都到字节了,他要的是位。
位操作 << >> 不就得了 何必纠结于 语言 语法