C# Tips: How to tell if system is little endian or big endian?

上回书说到,如果用C语言来判断系统的字节存储顺序 Little endian 和 Big endian ,函数如下:


    #include <stdint.h>  
    #include <stdio.h>  
    #include <stdlib.h>  
      
    union TestEndian_Unit  
    {  
        uint16_t value;  
        uint8_t bytes[2];  
    };  
      
    /*! 
        This function get endianness of current running environment. 
        Return value:   0 -- Little endian 
                        1 -- Big endian 
     
        Exception 0xFF00 means error occurs. 
         
        Reference: http://en.wikipedia.org/wiki/Endianness 
     
        For example:    x86, x86-64 and Windows on PowerPC use little endian; 
                        FreeBSD on PowerPC and SPARC use big endian. 
    */  
    int IsBigEndian()  
    {  
        union TestEndian_Unit flag;  
        flag.value = 0xFF00;  
        if(flag.bytes[0] == 0x00 && flag.bytes[1] == 0xFF)  
        {  
            return 0;  
        }  
        else if(flag.bytes[0] == 0xFF && flag.bytes[1] == 0x00)  
        {  
            return 1;  
        }  
        else  
        {  
            fprintf(stderr, "Error occurs in function IsBigEndian().\n");  
            exit(0xFF00);  
        }  
    }  


那么,如何用托管代码来进行同样的判断呢?

方法一、借助Marshal

代码如下:

// -----------------------------------------------------------------------
// <copyright file="SystemInfo.cs" Author="Yaping Xin">
// Helper class to get system information.
// </copyright>
// -----------------------------------------------------------------------

namespace TestEndian
{
    using System;
    using System.Runtime.InteropServices;

    /// <summary>
    /// Helper class to get system information.
    /// </summary>
    public class SystemInfo
    {
        /// <summary>
        /// This function get endianness of current running environment.
        /// Return value:   False -- Little endian
        ///                 True  -- Big endian
        /// Reference: http://en.wikipedia.org/wiki/Endianness
        /// 
        /// For example:    x86, x86-64 and Windows on PowerPC use little endian;
        ///                 FreeBSD on PowerPC and SPARC use big endian.
        /// </summary>
        /// <returns>True indicates big endian.</returns>
        public static bool IsBigEndian()
        {
            const UInt16 value = 0xFF00;
            byte[] bytes = ToBytes(value);

            if (bytes[0] == 0x00 && bytes[1] == 0xFF)
            {
                return false;
            }
            else if (bytes[0] == 0xFF && bytes[1] == 0x00)
            {
                return true;
            }
            else
            {
                throw new ArithmeticException(
                    "Error occurs while judge system endian.");
            }
        }

        /// <summary>
        /// Convert UInt16 value to byte[2] array.
        /// </summary>
        /// <param name="value">the UInt16 value</param>
        /// <returns>byte[2] array</returns>
        private static byte[] ToBytes(UInt16 value)
        {
            IntPtr buffer = Marshal.AllocHGlobal(2);
            try
            {
                Marshal.StructureToPtr(value, buffer, false);
                byte[] bytes = new byte[2];
                Marshal.Copy(buffer, bytes, 0, 2);
                return bytes;
            }
            catch (Exception ex)
            {
                string message = string.Format(
                    "Error occurs while converting {0} to byte[2] array.",
                    value);
                throw new Exception(message, ex.InnerException);
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }
    }
}


方法二、用C#来模拟C的Union结构

文件列表:

  1. TestEndianUnit.cs
  2. SystemInfo.cs

TestEndianUnit.cs

// -----------------------------------------------------------------------
// <copyright file="TestEndianUnit.cs" Author="Yaping Xin">
// Union structure to test system Endianness.
// </copyright>
// -----------------------------------------------------------------------

namespace TestEndian
{
    using System;
    using System.Runtime.InteropServices;

    /// <summary>
    /// Union structure to test system Endianness.
    /// The C union structure definition is as below:
    /// union TestEndian_Unit  
    /// {  
    ///     uint16_t value;  
    ///     uint8_t bytes[2];  
    /// };  
    /// </summary>
    [StructLayout(LayoutKind.Explicit)]
    public struct TestEndianUnit
    {
        #region Data field
        /// <summary>
        /// Data field as TestEndian_Unit.value
        /// </summary>
        [FieldOffset(0)]
        public UInt16 Value;

        /// <summary>
        /// Data field as TestEndian_Unit.bytes[0]
        /// </summary>
        [FieldOffset(0)]
        public byte HByte;

        /// <summary>
        /// Data field as TestEndian_Unit.bytes[1]
        /// </summary>
        [FieldOffset(1)]
        public byte LByte;
        #endregion

        #region Initialization
        /// <summary>
        /// Initializes a new instance of the TestEndianUnit struct.
        /// </summary>
        /// <param name="value">union struct value</param>
        public TestEndianUnit(UInt16 value)
        {
            this.HByte = 0;
            this.LByte = 0;
            this.Value = value;
        }
        #endregion
    }
}

SystemInfo.cs

// -----------------------------------------------------------------------
// <copyright file="SystemInfo.cs" Author="Yaping Xin">
// Helper class to get system information.
// </copyright>
// -----------------------------------------------------------------------

namespace TestEndian
{
    using System;

    /// <summary>
    /// Helper class to get system information.
    /// </summary>
    public class SystemInfo
    {
        /// <summary>
        /// This function get endianness of current running environment.
        /// Return value:   False -- Little endian
        ///                 True  -- Big endian
        /// Reference: http://en.wikipedia.org/wiki/Endianness
        /// 
        /// For example:    x86, x86-64 and Windows on PowerPC use little endian;
        ///                 FreeBSD on PowerPC and SPARC use big endian.
        /// </summary>
        /// <returns>True indicates big endian.</returns>
        public static bool IsBigEndian()
        {
            TestEndianUnit unit = new TestEndianUnit(0xFF00);

            if (unit.HByte == 0x00 && unit.LByte == 0xFF)
            {
                return false;
            }
            else if (unit.HByte == 0xFF && unit.LByte == 0x00)
            {
                return true;
            }
            else
            {
                throw new ArithmeticException(
                    "Error occurs while judge system endian.");
            }
        }
    }
}



方法三、用C#来模拟C的Union结构(unsafe)

文件列表:

  1. TestEndianUnit.cs
  2. SystemInfo.cs

TestEndianUnit.cs

// -----------------------------------------------------------------------
// <copyright file="TestEndianUnit.cs" Author="Yaping Xin">
// Union structure to test system Endianness.
// </copyright>
// -----------------------------------------------------------------------

namespace TestEndian
{
    using System;
    using System.Runtime.InteropServices;

    /// <summary>
    /// Union structure to test system Endianness.
    /// The C union structure definition is as below:
    /// union TestEndian_Unit  
    /// {  
    ///     uint16_t value;  
    ///     uint8_t bytes[2];  
    /// };  
    /// </summary>
    [StructLayout(LayoutKind.Explicit)]
    public unsafe struct TestEndianUnit
    {
        #region Data field
        /// <summary>
        /// Data field as TestEndian_Unit.value
        /// </summary>
        [FieldOffset(0)]
        public UInt16 Value;

        /// <summary>
        /// Data field as TestEndian_Unit.bytes
        /// </summary>
        [FieldOffset(0)]
        public fixed byte Bytes[2];
        #endregion

        #region Initialization
        /// <summary>
        /// Initializes a new instance of the TestEndianUnit struct.
        /// </summary>
        /// <param name="value">union struct value</param>
        public TestEndianUnit(UInt16 value)
        {
            this.Value = value;
        }
        #endregion
    }
}

SystemInfo.cs

// -----------------------------------------------------------------------
// <copyright file="SystemInfo.cs" Author="Yaping Xin">
// Helper class to get system information.
// </copyright>
// -----------------------------------------------------------------------

namespace TestEndian
{
    using System;

    /// <summary>
    /// Helper class to get system information.
    /// </summary>
    public class SystemInfo
    {
        /// <summary>
        /// This function get endianness of current running environment.
        /// Return value:   False -- Little endian
        ///                 True  -- Big endian
        /// Reference: http://en.wikipedia.org/wiki/Endianness
        /// 
        /// For example:    x86, x86-64 and Windows on PowerPC use little endian;
        ///                 FreeBSD on PowerPC and SPARC use big endian.
        /// </summary>
        /// <returns>True indicates big endian.</returns>
        public static unsafe bool IsBigEndian()
        {
            TestEndianUnit unit = new TestEndianUnit(0xFF00);

            if (unit.Bytes[0] == 0x00 && unit.Bytes[1] == 0xFF)
            {
                return false;
            }
            else if (unit.Bytes[0] == 0xFF && unit.Bytes[1] == 0x00)
            {
                return true;
            }
            else
            {
                throw new ArithmeticException(
                    "Error occurs while judge system endian.");
            }
        }
    }
}

需要注意的是:方法三的代码需要在Project中打开“unsafe”选项才可编译,如图:




参考文献:

  1. C Tips: How to tell if system is little endian or big endian? http://blog.csdn.net/xinyaping/article/details/7450920
  2. Endianness http://en.wikipedia.org/wiki/Endianness
  3. Big and Little Endian http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值