刚从C++转过来,一个位域的问题犯晕,谁能帮帮我。。。

时间:2021-07-19 11:04:27
以前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#如何实现以上代码啊?

67 个解决方案

#1


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

#2


struct _cmdTag
{
  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)
  {
  ...
  }
  ...
}

#3


移植干嘛?如果可能,删除以前的东西吧。重新开始学编程。

#4


如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。

#5


引用 3 楼 sp1234 的回复:
移植干嘛?如果可能,删除以前的东西吧。重新开始学编程。


Ok,删除以前的东西重新用C#编程,
那么C++实现的那个代码,
请问用C#如何实现?
谢谢!

#6


引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。


这不是理论,
这是实实在在、普普通通的C++代码,
老哥!
你没写过这方面的代码,
拜托你不要用“理论”一次来形容它好吗?

#7


引用 1 楼 wuyq11 的回复:
++ 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


看不出你链接指向的帖子与我这个问题的联系。

#8


非指针写法
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)
  {
  ...
  }
  ...
}

#9


引用 8 楼 lizhibin11 的回复:
非指针写法
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.c……


谢谢您!
不过老哥,
请您先弄明白什么叫做C++的“位域”吧!

#10


C#当前版本不支持位域

#11


引用 9 楼 chinaos 的回复:
引用 8 楼 lizhibin11 的回复:
非指针写法
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#好像做不到

#12


凡是把下面代码:
//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++的“位域”,
谢谢!

#13


引用 10 楼 wuyq11 的回复:
C#当前版本不支持位域

看来这个小问题,
竟然遇到大麻烦了,
老板让我们转到C#,
看来C#并不能完成C++所能完成的全部功能啊。

#14


引用 3 楼 sp1234 的回复:
移植干嘛?如果可能,删除以前的东西吧。重新开始学编程。

从应用的层面来说,一个语言能够实现的功能,几乎都能够用其它任何一种合格的语言来实现,其区别只有编码效率和运行效率的区别。就像SP1234说的,不要纠结这些细节,用C#重写一次就行了

#15


帮你查到一篇,是这个
http://topic.csdn.net/t/20030531/22/1860471.html

#16


引用 11 楼 lizhibin11 的回复:
要那么严格的话,C#好像做不到

微软不是号称C#无所不能吗,
能完成C++所有的功能吗?
晕,到底转向C#可以吗?

#17


引用 14 楼 zhoujk 的回复:
引用 3 楼 sp1234 的回复:
移植干嘛?如果可能,删除以前的东西吧。重新开始学编程。

从应用的层面来说,一个语言能够实现的功能,几乎都能够用其它任何一种合格的语言来实现,其区别只有编码效率和运行效率的区别。就像SP1234说的,不要纠结这些细节,用C#重写一次就行了

我丝毫不像纠结于什么细节,
我就想知道C#该如何重写它,
仅此而已!

#18


引用 16 楼 chinaos 的回复:
引用 11 楼 lizhibin11 的回复:
要那么严格的话,C#好像做不到
微软不是号称C#无所不能吗,
能完成C++所有的功能吗?
晕,到底转向C#可以吗?

“微软不是号称C#无所不能吗,”,没听说过啊。

#19


udp组包的时候用过,原来这个叫位域啊
上面这个帖子牛,想到枚举

#20


引用 15 楼 lizhibin11 的回复:
帮你查到一篇,是这个
http://topic.csdn.net/t/20030531/22/1860471.html


谢谢!那个帖子的问题与我这个问题有相似的地方,
但是它那是用C#的枚举解决问题,
但这是不行的,例如:
struct _cmdTag
{
  unsigned int cmd:4;
  unsigned int active:1; 
  unsigned int frame_len:27;
};
就没法解决,因为frame_len是表示27bit的整数值。
   

#21


引用 19 楼 sj97a007 的回复:
udp组包的时候用过,原来这个叫位域啊
上面这个帖子牛,想到枚举


用枚举不行,请看我的帖子。

#22


引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。


这些拿微软一些控件来写界面的所谓“程序员”,
真让人抓狂啊,
还怪别人搞些“理论的东西”!

#23


以前用c组过mac帧,的确比c#方便很多,后来再做都是用整形和字符串组byte,没想到什么好办法

#24


http://archive.cnblogs.com/a/1942446/

#25


脑筋不要这么死板好不好,c++有位域,c#就一定要支持?那要让你把C++的代码给改成perl的,你不是要抓狂了。
你那个结构用C#写成下面这样,浪费一点空间不就完了,active的类型也可以改成bool。移植程序嘛,灵活一点。要是什么都完全一样,就用不着移植了

struct _cmdTag
{
  unsigned char cmd;
  unsigned char cmd_type;
  unsigned char active;
};

#26


引用 25 楼 assassin5616 的回复:
脑筋不要这么死板好不好,c++有位域,c#就一定要支持?那要让你把C++的代码给改成perl的,你不是要抓狂了。
你那个结构用C#写成下面这样,浪费一点空间不就完了,active的类型也可以改成bool。移植程序嘛,灵活一点。要是什么都完全一样,就用不着移植了

struct _cmdTag
{
  unsigned char cmd;
  unsigned char cmd_type……


朋友,你没有写过类似的东西,可能没法理解
例如
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#还没有发现可以达到这种目的的方法,当然可能是我才疏学浅

#27


楼主啊,不管数据帧内各部分是什么,最后组包完毕总是byte的整数倍
所以如果没什么好办法的话,用char或者其他类型作为结构体的成员类型,敷值完毕以后自己计算byte

很傻,不过能做出来

C#有自己的优势,不过底层的东西,还是C比较方便

#28


话说好久没写C了,貌似有些写错了,各位看官莫笑

#29



不知道这样行不


 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));
            }
        }


    }

#30


抱歉有点错误

if (str == "cmd") _v = (byte)((_v&0xf)|(value<<4));
                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));

#31


楼上那个写得很好了,我再班门弄斧一下,哈哈
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();
        }

#32


C#不能直接实现,自己做位运算吧。

#33


C#肯定不能直接提供你想要的这种功能,你需要像后面几位回复写的那样,写一些把结构体转换成字符流的代码。肯定要比C++麻烦,这是语言本身决定了的。还是那句话,要是把这段代码转换成perl,你怎么办?多想办法,多绕弯子嘛,移植的工作量就是在这些东西方面了

引用 26 楼 sj97a007 的回复:
引用 25 楼 assassin5616 的回复:
脑筋不要这么死板好不好,c++有位域,c#就一定要支持?那要让你把C++的代码给改成perl的,你不是要抓狂了。
你那个结构用C#写成下面这样,浪费一点空间不就完了,active的类型也可以改成bool。移植程序嘛,灵活一点。要是什么都完全一样,就用不着移植了

struct _cmdTag
{
unsigned char cmd;……

#34


该回复于2011-02-09 10:44:01被版主删除

#35


try like this

using System;

namespace BitfieldTest
{
  [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;
    }
  }
}

#36


直接的没有。不过间接的方法还是很多的。

#37


引用 25 楼 assassin5616 的回复:
脑筋不要这么死板好不好,c++有位域,c#就一定要支持?那要让你把C++的代码给改成perl的,你不是要抓狂了。
你那个结构用C#写成下面这样,浪费一点空间不就完了,active的类型也可以改成bool。移植程序嘛,灵活一点。要是什么都完全一样,就用不着移植了

struct _cmdTag
{
  unsigned char cmd;
  unsigned char cmd_type……


你说得倒是好,
改下代码就行吗?
把所有设备的代码都改变吗?
那么请说服大家把TCP等等协议都改变吧!

#38


引用 24 楼 microtry 的回复:
http://archive.cnblogs.com/a/1942446/


感觉绕了很大弯,
挺费劲的。

#39


引用 29 楼 lu142857 的回复:
不知道这样行不


C# code

 class Program
    {
        static void Main(string[] args)
        {
            CmdTag ct = new CmdTag(25);
            Console.WriteLine(string.Format("cmd:{0} cmdType……


谢谢您的鼎力帮助,
感觉费了挺大的劲儿,
费了九牛二虎之力,
效果还够呛,
看来用C#写底层代码,
还真的不行,
得给老板建议不要转向C#了。

#40


这样的贸然转型确实很危险,以LZ目前对C#的了解,即使转过来,项目或产品的质量也是无法保证的,尤其是涉及这种底层细节,需要有足够经验积累才可以。如果老板非要转的话,LZ可以建议先把一些简单、C#有优势的部分做移植

引用 39 楼 chinaos 的回复:
谢谢您的鼎力帮助,
感觉费了挺大的劲儿,
费了九牛二虎之力,
效果还够呛,
看来用C#写底层代码,
还真的不行,
得给老板建议不要转向C#了。

#41


引用 40 楼 litaoye 的回复:
这样的贸然转型确实很危险,以LZ目前对C#的了解,即使转过来,项目或产品的质量也是无法保证的,尤其是涉及这种底层细节,需要有足够经验积累才可以。如果老板非要转的话,LZ可以建议先把一些简单、C#有优势的部分做移植


引用 39 楼 chinaos 的回复:
谢谢您的鼎力帮助,
感觉费了挺大的劲儿,
费了九牛二虎之力,
效果还够呛,
看来用C#写底层代码,
还真的不行,
得给老……


看来界面部分可以先转到C#,
底层代码还是要用C++。

#42


引用 35 楼 i_mimi 的回复:
try like this

C# code

using System;

namespace BitfieldTest
{
  [global::System.AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
  sealed class BitfieldLengthAttribute : Attri……

谢谢!您的方法感觉比较可行,
由于我对C#了解有限,所以代码还需验证。

#43


引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。
总算听到了有哲理的话。

#44


引用 43 楼 madaming 的回复:
引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。
总算听到了有哲理的话。


算啦吧,不懂装懂,
见过巴掌大的天,
就以为自己的办法天下都通用。

#45


引用 43 楼 madaming 的回复:
引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。
总算听到了有哲理的话。


说什么“性能”、“空间”啊之类的话,
我问的问题与性能之类的东西有什么关系呢?
你以为这都是C++的人故意显示自己水平高,
故意造作使用位域吗?
不懂你就别跟着别人屁股后瞎嚷嚷了,
让人看得你的根基有多浅薄。

#46


真晕啊,
问了个位域问题,
硬是让一帮人说C++故意执拗于性能,
故意钻牛角之类显示自己理论多高的样子,
说白了,做应用软件的人,
很难理解底层为什么要这么做,
真是不做一行,不懂一行啊,
希望那些没有做过底层的,
不要再以此来讥讽了,
做C++的并不是为显摆才让代码那样子,
我也知道了C#的局限,
所以转入C#也会深重考虑了。

#47


_cmdTag c = new _cmdTag();
  c.cmd = b[0];
  c.cmd_type = b[1];
  c.active = b[2];
  return c;
  }
};

#48


好難懂,在學習中

#49


各位仙人非同一般//我也喜欢还是喜欢C

#50


To ChinaOS
非托管 转 托管的时候并不一定要把代码全部重写,也可以试着将非托管的部分封装成dll,给托管代码调用
像bitfield 及 union等最好能通过接口封装掉,不是说C#不能调,而是降低调用的麻烦程度,凡事有个度,具体事情具体衡量。

PS:某些人回答问题最好能看清楚别人问的问题是什么才回答,而不是一上来就否定人家,给出的建议也没什么建树,不知所云,不止在一个帖子里看到这样的回答,忍不住多嘴一句。

#1


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

#2


struct _cmdTag
{
  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)
  {
  ...
  }
  ...
}

#3


移植干嘛?如果可能,删除以前的东西吧。重新开始学编程。

#4


如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。

#5


引用 3 楼 sp1234 的回复:
移植干嘛?如果可能,删除以前的东西吧。重新开始学编程。


Ok,删除以前的东西重新用C#编程,
那么C++实现的那个代码,
请问用C#如何实现?
谢谢!

#6


引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。


这不是理论,
这是实实在在、普普通通的C++代码,
老哥!
你没写过这方面的代码,
拜托你不要用“理论”一次来形容它好吗?

#7


引用 1 楼 wuyq11 的回复:
++ 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


看不出你链接指向的帖子与我这个问题的联系。

#8


非指针写法
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)
  {
  ...
  }
  ...
}

#9


引用 8 楼 lizhibin11 的回复:
非指针写法
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.c……


谢谢您!
不过老哥,
请您先弄明白什么叫做C++的“位域”吧!

#10


C#当前版本不支持位域

#11


引用 9 楼 chinaos 的回复:
引用 8 楼 lizhibin11 的回复:
非指针写法
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#好像做不到

#12


凡是把下面代码:
//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++的“位域”,
谢谢!

#13


引用 10 楼 wuyq11 的回复:
C#当前版本不支持位域

看来这个小问题,
竟然遇到大麻烦了,
老板让我们转到C#,
看来C#并不能完成C++所能完成的全部功能啊。

#14


引用 3 楼 sp1234 的回复:
移植干嘛?如果可能,删除以前的东西吧。重新开始学编程。

从应用的层面来说,一个语言能够实现的功能,几乎都能够用其它任何一种合格的语言来实现,其区别只有编码效率和运行效率的区别。就像SP1234说的,不要纠结这些细节,用C#重写一次就行了

#15


帮你查到一篇,是这个
http://topic.csdn.net/t/20030531/22/1860471.html

#16


引用 11 楼 lizhibin11 的回复:
要那么严格的话,C#好像做不到

微软不是号称C#无所不能吗,
能完成C++所有的功能吗?
晕,到底转向C#可以吗?

#17


引用 14 楼 zhoujk 的回复:
引用 3 楼 sp1234 的回复:
移植干嘛?如果可能,删除以前的东西吧。重新开始学编程。

从应用的层面来说,一个语言能够实现的功能,几乎都能够用其它任何一种合格的语言来实现,其区别只有编码效率和运行效率的区别。就像SP1234说的,不要纠结这些细节,用C#重写一次就行了

我丝毫不像纠结于什么细节,
我就想知道C#该如何重写它,
仅此而已!

#18


引用 16 楼 chinaos 的回复:
引用 11 楼 lizhibin11 的回复:
要那么严格的话,C#好像做不到
微软不是号称C#无所不能吗,
能完成C++所有的功能吗?
晕,到底转向C#可以吗?

“微软不是号称C#无所不能吗,”,没听说过啊。

#19


udp组包的时候用过,原来这个叫位域啊
上面这个帖子牛,想到枚举

#20


引用 15 楼 lizhibin11 的回复:
帮你查到一篇,是这个
http://topic.csdn.net/t/20030531/22/1860471.html


谢谢!那个帖子的问题与我这个问题有相似的地方,
但是它那是用C#的枚举解决问题,
但这是不行的,例如:
struct _cmdTag
{
  unsigned int cmd:4;
  unsigned int active:1; 
  unsigned int frame_len:27;
};
就没法解决,因为frame_len是表示27bit的整数值。
   

#21


引用 19 楼 sj97a007 的回复:
udp组包的时候用过,原来这个叫位域啊
上面这个帖子牛,想到枚举


用枚举不行,请看我的帖子。

#22


引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。


这些拿微软一些控件来写界面的所谓“程序员”,
真让人抓狂啊,
还怪别人搞些“理论的东西”!

#23


以前用c组过mac帧,的确比c#方便很多,后来再做都是用整形和字符串组byte,没想到什么好办法

#24


http://archive.cnblogs.com/a/1942446/

#25


脑筋不要这么死板好不好,c++有位域,c#就一定要支持?那要让你把C++的代码给改成perl的,你不是要抓狂了。
你那个结构用C#写成下面这样,浪费一点空间不就完了,active的类型也可以改成bool。移植程序嘛,灵活一点。要是什么都完全一样,就用不着移植了

struct _cmdTag
{
  unsigned char cmd;
  unsigned char cmd_type;
  unsigned char active;
};

#26


引用 25 楼 assassin5616 的回复:
脑筋不要这么死板好不好,c++有位域,c#就一定要支持?那要让你把C++的代码给改成perl的,你不是要抓狂了。
你那个结构用C#写成下面这样,浪费一点空间不就完了,active的类型也可以改成bool。移植程序嘛,灵活一点。要是什么都完全一样,就用不着移植了

struct _cmdTag
{
  unsigned char cmd;
  unsigned char cmd_type……


朋友,你没有写过类似的东西,可能没法理解
例如
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#还没有发现可以达到这种目的的方法,当然可能是我才疏学浅

#27


楼主啊,不管数据帧内各部分是什么,最后组包完毕总是byte的整数倍
所以如果没什么好办法的话,用char或者其他类型作为结构体的成员类型,敷值完毕以后自己计算byte

很傻,不过能做出来

C#有自己的优势,不过底层的东西,还是C比较方便

#28


话说好久没写C了,貌似有些写错了,各位看官莫笑

#29



不知道这样行不


 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));
            }
        }


    }

#30


抱歉有点错误

if (str == "cmd") _v = (byte)((_v&0xf)|(value<<4));
                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));

#31


楼上那个写得很好了,我再班门弄斧一下,哈哈
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();
        }

#32


C#不能直接实现,自己做位运算吧。

#33


C#肯定不能直接提供你想要的这种功能,你需要像后面几位回复写的那样,写一些把结构体转换成字符流的代码。肯定要比C++麻烦,这是语言本身决定了的。还是那句话,要是把这段代码转换成perl,你怎么办?多想办法,多绕弯子嘛,移植的工作量就是在这些东西方面了

引用 26 楼 sj97a007 的回复:
引用 25 楼 assassin5616 的回复:
脑筋不要这么死板好不好,c++有位域,c#就一定要支持?那要让你把C++的代码给改成perl的,你不是要抓狂了。
你那个结构用C#写成下面这样,浪费一点空间不就完了,active的类型也可以改成bool。移植程序嘛,灵活一点。要是什么都完全一样,就用不着移植了

struct _cmdTag
{
unsigned char cmd;……

#34


该回复于2011-02-09 10:44:01被版主删除

#35


try like this

using System;

namespace BitfieldTest
{
  [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;
    }
  }
}

#36


直接的没有。不过间接的方法还是很多的。

#37


引用 25 楼 assassin5616 的回复:
脑筋不要这么死板好不好,c++有位域,c#就一定要支持?那要让你把C++的代码给改成perl的,你不是要抓狂了。
你那个结构用C#写成下面这样,浪费一点空间不就完了,active的类型也可以改成bool。移植程序嘛,灵活一点。要是什么都完全一样,就用不着移植了

struct _cmdTag
{
  unsigned char cmd;
  unsigned char cmd_type……


你说得倒是好,
改下代码就行吗?
把所有设备的代码都改变吗?
那么请说服大家把TCP等等协议都改变吧!

#38


引用 24 楼 microtry 的回复:
http://archive.cnblogs.com/a/1942446/


感觉绕了很大弯,
挺费劲的。

#39


引用 29 楼 lu142857 的回复:
不知道这样行不


C# code

 class Program
    {
        static void Main(string[] args)
        {
            CmdTag ct = new CmdTag(25);
            Console.WriteLine(string.Format("cmd:{0} cmdType……


谢谢您的鼎力帮助,
感觉费了挺大的劲儿,
费了九牛二虎之力,
效果还够呛,
看来用C#写底层代码,
还真的不行,
得给老板建议不要转向C#了。

#40


这样的贸然转型确实很危险,以LZ目前对C#的了解,即使转过来,项目或产品的质量也是无法保证的,尤其是涉及这种底层细节,需要有足够经验积累才可以。如果老板非要转的话,LZ可以建议先把一些简单、C#有优势的部分做移植

引用 39 楼 chinaos 的回复:
谢谢您的鼎力帮助,
感觉费了挺大的劲儿,
费了九牛二虎之力,
效果还够呛,
看来用C#写底层代码,
还真的不行,
得给老板建议不要转向C#了。

#41


引用 40 楼 litaoye 的回复:
这样的贸然转型确实很危险,以LZ目前对C#的了解,即使转过来,项目或产品的质量也是无法保证的,尤其是涉及这种底层细节,需要有足够经验积累才可以。如果老板非要转的话,LZ可以建议先把一些简单、C#有优势的部分做移植


引用 39 楼 chinaos 的回复:
谢谢您的鼎力帮助,
感觉费了挺大的劲儿,
费了九牛二虎之力,
效果还够呛,
看来用C#写底层代码,
还真的不行,
得给老……


看来界面部分可以先转到C#,
底层代码还是要用C++。

#42


引用 35 楼 i_mimi 的回复:
try like this

C# code

using System;

namespace BitfieldTest
{
  [global::System.AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
  sealed class BitfieldLengthAttribute : Attri……

谢谢!您的方法感觉比较可行,
由于我对C#了解有限,所以代码还需验证。

#43


引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。
总算听到了有哲理的话。

#44


引用 43 楼 madaming 的回复:
引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。
总算听到了有哲理的话。


算啦吧,不懂装懂,
见过巴掌大的天,
就以为自己的办法天下都通用。

#45


引用 43 楼 madaming 的回复:
引用 4 楼 sp1234 的回复:
如果你深陷于什么性能、空间的纠结里出不来,对你的应用程序(而是简单地一两条语句)进行测试,看看这个纠结值几毛钱,可以不可以不问自己“请问C#如何实现以上代码”的问题的情况下同样完成自己的任务、赢得用户,这就够了。

测试来说了算,不要搞理论。
总算听到了有哲理的话。


说什么“性能”、“空间”啊之类的话,
我问的问题与性能之类的东西有什么关系呢?
你以为这都是C++的人故意显示自己水平高,
故意造作使用位域吗?
不懂你就别跟着别人屁股后瞎嚷嚷了,
让人看得你的根基有多浅薄。

#46


真晕啊,
问了个位域问题,
硬是让一帮人说C++故意执拗于性能,
故意钻牛角之类显示自己理论多高的样子,
说白了,做应用软件的人,
很难理解底层为什么要这么做,
真是不做一行,不懂一行啊,
希望那些没有做过底层的,
不要再以此来讥讽了,
做C++的并不是为显摆才让代码那样子,
我也知道了C#的局限,
所以转入C#也会深重考虑了。

#47


_cmdTag c = new _cmdTag();
  c.cmd = b[0];
  c.cmd_type = b[1];
  c.active = b[2];
  return c;
  }
};

#48


好難懂,在學習中

#49


各位仙人非同一般//我也喜欢还是喜欢C

#50


To ChinaOS
非托管 转 托管的时候并不一定要把代码全部重写,也可以试着将非托管的部分封装成dll,给托管代码调用
像bitfield 及 union等最好能通过接口封装掉,不是说C#不能调,而是降低调用的麻烦程度,凡事有个度,具体事情具体衡量。

PS:某些人回答问题最好能看清楚别人问的问题是什么才回答,而不是一上来就否定人家,给出的建议也没什么建树,不知所云,不止在一个帖子里看到这样的回答,忍不住多嘴一句。