none
Marshal.ReadByte RRS feed

  • 問題

  • 各位大大好!

    小弟有一個不解的問題,向大家請教一下,在於記憶體空間內 Byte 是屬一個位元,但個人使用了 Marshal.ReadByte 的方法會讀取到兩個位元以下為正常的方式

     Public Structure f_stru
              Dim std_ucode As Byte
              Dim std_ucode3 As Byte
     End Structure

    Dim p As New f_stru
    p.std_ucode = &H24
    p.std_ucode3 = &H53
    Dim IIII As Integer = Marshal.SizeOf(p) - 1
    Dim BBB(IIII) As Byte
                    For I As Integer = 0 To IIII
                       BBB(I) = Marshal.ReadByte(p, I)
                   Next
    =============結果=================
    BBB(0)=36
    BBB(1)=86
    ===============以下為修改後==================

     Public Structure f_stru
              Dim std_ucode As Byte
              Dim act_fval As UShort     <====多加一個結構
              Dim std_ucode3 As Byte
     End Structure

    Dim p As New f_stru
    p.std_ucode = &H24
    p.act_fval = 2320
    p.std_ucode3 = &H53
    Dim IIII As Integer = Marshal.SizeOf(p) - 1
    Dim BBB(IIII) As Byte
                    For I As Integer = 0 To IIII
                       BBB(I) = Marshal.ReadByte(p, I)
                   Next
    ==============結果=================
    BBB(0)=36 
    BBB(1)=0                <=====多出來的
    BBB(2)=16
    BBB(3)=9
    BBB(4)=83
    BBB(5)=0                <
    =====多出來的

    為何會多出兩個位元。請前輩指點迷律!


    2017年10月25日 上午 06:36

解答

  • 你讀取的是 unmanaged memory 的資料,當一個資料從 managed memory 封送到  unmanaged memory 時,他未必會保持原來的大小,有可能因為設定改變欄位對齊的方式。

    在沒有特別指定的狀況下,封送行為會採取最大的欄位長度作為對齊基準。

    你也可以強迫他照你的意思排列,如以下的範例。

        class Program
        {
            static void Main(string[] args)
            {            
                Test t = new Test();
                t.x = 3;
                t.y = 513;
                t.z = 86;
                var size =  Marshal.SizeOf(t);
                Console.WriteLine($"Size : {size}");
               for(int i=0; i < size; i++)
                {
                    Console.WriteLine(Marshal.ReadByte(t, i));
                }
                Console.ReadLine();
            }
        }
    
        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public struct Test
        {
            [FieldOffset (0)]
            public byte x;
            [FieldOffset(1)]
            public ushort y;
            [FieldOffset(3)]
            public byte z;
        }

      

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 雲龍 2017年10月25日 下午 02:16
    2017年10月25日 上午 09:20
    版主
  • 這兩篇看看:

    .Net framework 讀取結構作法 (VBNET)

    [VB2008] 結構或類別中 LayoutKind.Sequential 跟泛型不能同時使用


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 雲龍 2017年10月25日 下午 02:16
    2017年10月25日 上午 10:53
  • 同心冷的說法, 加個 pack

    類似這樣

    [StructLayout(LayoutKind.Explicit,CharSet = CharSet.Ansi,Pack =1)]


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 雲龍 2017年10月25日 下午 02:16
    2017年10月25日 上午 11:56
    版主

所有回覆

  • 你讀取的是 unmanaged memory 的資料,當一個資料從 managed memory 封送到  unmanaged memory 時,他未必會保持原來的大小,有可能因為設定改變欄位對齊的方式。

    在沒有特別指定的狀況下,封送行為會採取最大的欄位長度作為對齊基準。

    你也可以強迫他照你的意思排列,如以下的範例。

        class Program
        {
            static void Main(string[] args)
            {            
                Test t = new Test();
                t.x = 3;
                t.y = 513;
                t.z = 86;
                var size =  Marshal.SizeOf(t);
                Console.WriteLine($"Size : {size}");
               for(int i=0; i < size; i++)
                {
                    Console.WriteLine(Marshal.ReadByte(t, i));
                }
                Console.ReadLine();
            }
        }
    
        [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)]
        public struct Test
        {
            [FieldOffset (0)]
            public byte x;
            [FieldOffset(1)]
            public ushort y;
            [FieldOffset(3)]
            public byte z;
        }

      

    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 雲龍 2017年10月25日 下午 02:16
    2017年10月25日 上午 09:20
    版主
  • 感謝大大的指導,目前的結果確為我要的,只是還有一事不懂,可否再指導一下,
    <FieldOffset(0)>    <===== 之間的數值定義是如何設定的,為何0=>1=>3,但沒有2 的值,個人的理解為位元數的安排,因此我加大了組別,但會多個尾數出來是屬正常嗎?
     Public Structure f_stru
              <FieldOffset(0)>
              Dim std_ucode As Byte
              <FieldOffset(1)>
              Dim STD_fval As UShort
              <FieldOffset(3)>
              Dim ACT_ucode As Byte
              <FieldOffset(4)>
              Dim ACT_fval As UShort
              <FieldOffset(6)>
              Dim Meas_ucode As Byte
              <FieldOffset(7)>
              Dim Meas_fval As UShort
         End Structure
         Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
              Dim p As New f_stru
              With p
                   .std_ucode = &H66
                   .STD_fval = 266
                   .ACT_ucode = &H67
                   .ACT_fval = 267
                   .Meas_ucode = &H68
                   .Meas_fval = 268
              End With
              Dim IIII As Integer = Marshal.SizeOf(p) - 1
              Dim BBB(IIII) As Byte
              For I As Integer = 0 To IIII
                   BBB(I) = Marshal.ReadByte(p, I)
              Next
         End Sub
    ===============結果===================
    BBB(0)=102
    BBB(1)=10
    BBB(2)=1
    BBB(3)=103
    BBB(4)=11
    BBB(5)=1
    BBB(6)=104
    BBB(7)=12
    BBB(8)=1
    BBB(9)=0        <====多個尾數

    另再請教,因我是從BCB 3.1(DOS)的程式,把它升級到VB.Net(2015),因前人使用了大量的記憶體搬運所以我才要如此的動作,如您所提,我是使用 unmanaged memory的方式,不知是否還有其他的方式可以做到此功能(除了API),是否可以請大大提供方向。
    2017年10月25日 上午 10:35
  • 這兩篇看看:

    .Net framework 讀取結構作法 (VBNET)

    [VB2008] 結構或類別中 LayoutKind.Sequential 跟泛型不能同時使用


    不精確的問法,就會得到隨便猜的答案;自己都不肯花時間好好描述問題,又何必期望網友會認真回答?

    • 已標示為解答 雲龍 2017年10月25日 下午 02:16
    2017年10月25日 上午 10:53
  • 同心冷的說法, 加個 pack

    類似這樣

    [StructLayout(LayoutKind.Explicit,CharSet = CharSet.Ansi,Pack =1)]


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。

    • 已標示為解答 雲龍 2017年10月25日 下午 02:16
    2017年10月25日 上午 11:56
    版主