Как получить верхний и Нижний байт целого числа в C# и поместить его в массив символов для отправки в com-порт?

В C я бы сделал это

int number = 3510;

char upper = число > > 8;

char lower = число & & 8;

SendByte(верхняя часть);

SendByte(нижняя);

где верхний и Нижний оба = 54

В C# я делаю это:

            int number = Convert.ToInt16("3510");
            byte upper = byte(number >> 8);
            byte lower = byte(number & 8);
            char upperc = Convert.ToChar(upper);
            char lowerc = Convert.ToChar(lower);
            data = "GETDM" + upperc + lowerc;
            comport.Write(data);

однако в отладчике number = 3510, upper = 13 и lower = 0 это не имеет смысла, если я измените код на >> 6 upper = 54, что абсолютно странно.

в основном я просто хочу получить верхний и Нижний байт из 16-битного номера и отправить его через com-порт после "GETDM"

Как я могу это сделать? Это так просто в C, но в C# я полностью в тупике.

5 ответов


ваша маскировка неверна - вы должны маскироваться против 255 (0xff) вместо 8. Сдвиг работает с точки зрения" битов для сдвига", тогда как побитовые и/или работают против значения для маски... поэтому, если вы хотите сохранить только нижние 8 бит, вам нужна маска, которая имеет только нижние 8 бит-т. е. 255.

обратите внимание, что если вы пытаетесь разделить число на два байта, это действительно должно быть короткое или ushort для начала, а не int (имеющего четыре байты.)

ushort number = Convert.ToUInt16("3510");
byte upper = (byte) (number >> 8);
byte lower = (byte) (number & 0xff);

обратите внимание, что я использовал ushort здесь вместо byte как побитовая арифметика легче думать, когда вам не нужно беспокоиться о расширении знака. На самом деле это не имеет значения в этом случае из-за того, как сужающееся преобразование в byte работает, но это то, о чем вы должны думать.


вы, вероятно, хотите и это с 0x00FF

byte lower = Convert.ToByte(number & 0x00FF);

полный пример:

ushort number = Convert.ToUInt16("3510");
byte upper = Convert.ToByte(number >> 8);
byte lower = Convert.ToByte(number & 0x00FF);
char upperc = Convert.ToChar(upper);
char lowerc = Convert.ToChar(lower);
data = "GETDM" + upperc + lowerc;

разве это не должно быть:

byte lower = (byte) ( number & 0xFF );

даже если принятый ответ соответствует вопросу, я считаю его неполным из-за простого факта, что вопрос содержит int, а не короткий заголовок, и он вводит в заблуждение в результатах поиска, и, как мы знаем, Int32 в C# имеет 32 бита и, следовательно, 4 байта. Я опубликую здесь пример, который будет полезен в случае использования Int32. В случае Int32 мы есть:

  1. LowWordLowByte
  2. LowWordHighByte
  3. HighWordLowByte
  4. HighWordHighByte.

и как таковой, я создал следующий метод для преобразования значения Int32 в маленькую шестнадцатеричную строку endian, в которой каждый байт отделен от других пробелом. Это полезно, когда вы передаете данные и хотите, чтобы приемник делал обработку быстрее, он может просто разделить (" " ) и получить байты, представленные как автономные шестнадцатеричные строки.

public static String IntToLittleEndianWhitespacedHexString(int pValue, uint pSize)
{
    String result = String.Empty;

    pSize = pSize < 4 ? pSize : 4;

    byte tmpByte = 0x00;
    for (int i = 0; i < pSize; i++)
    {
        tmpByte = (byte)((pValue >> i * 8) & 0xFF);
        result += tmpByte.ToString("X2") + " ";
    }

    return result.TrimEnd(' ');
}

использование:

String value1 = ByteArrayUtils.IntToLittleEndianWhitespacedHexString(0x927C, 4);
String value2 = ByteArrayUtils.IntToLittleEndianWhitespacedHexString(0x3FFFF, 4);
String value3 = ByteArrayUtils.IntToLittleEndianWhitespacedHexString(0x927C, 2);
String value4 = ByteArrayUtils.IntToLittleEndianWhitespacedHexString(0x3FFFF, 1);

результат:

  1. 7C 92 00 00
  2. FF FF 03 00
  3. 7С 92
  4. FF.

Если трудно понять метод, который я создал, то следующее Может быть более понятным:

public static String IntToLittleEndianWhitespacedHexString(int pValue)
{
    String result = String.Empty;
    byte lowWordLowByte = (byte)(pValue & 0xFF);
    byte lowWordHighByte = (byte)((pValue >> 8) & 0xFF);
    byte highWordLowByte = (byte)((pValue >> 16) & 0xFF);
    byte highWordHighByte = (byte)((pValue >> 24) & 0xFF);

    result = lowWordLowByte.ToString("X2") + " " +
            lowWordHighByte.ToString("X2") + " " +
            highWordLowByte.ToString("X2") + " " +
            highWordHighByte.ToString("X2");

    return result;
}

Примечания:

  1. конечно insteand uint pSize может быть перечисление, указывающее байт, слово, Двойное слово!--7-->
  2. вместо преобразования в шестнадцатеричную строку и создания маленькой строки endian вы можете конвертировать в символы и делать все, что хотите.

надеюсь, что это поможет кому-то!


чтобы быть немного более творческим

[System.Runtime.InteropServices.StructLayout( System.Runtime.InteropServices.LayoutKind.Explicit )]
public struct IntToBytes {
    [System.Runtime.InteropServices.FieldOffset(0)]
    public int Int32;
    [System.Runtime.InteropServices.FieldOffset(0)]
    public byte First;
    [System.Runtime.InteropServices.FieldOffset(1)]
    public byte Second;
    [System.Runtime.InteropServices.FieldOffset(2)]
    public byte Third;
    [System.Runtime.InteropServices.FieldOffset(3)]
    public byte Fourth;
}