您的位置:首页 > 编程语言 > C#

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

2012-04-20 05:13 579 查看
上回书说到,如果用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结构

文件列表:

TestEndianUnit.cs
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)

文件列表:

TestEndianUnit.cs
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”选项才可编译,如图:



参考文献:

C Tips: How to tell if system is little endian or big endian? http://blog.csdn.net/xinyaping/article/details/7450920 Endianness http://en.wikipedia.org/wiki/Endianness Big and Little Endian http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Data/endian.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息