What byte order when BitConverter.IsLittleEndian = false - c#

I'm storing numbers in their byte equivalent format, using the least number of bytes possible. With the range 65535 through 16777215, BitConverter gives me a 4 byte array, but I want to only store 3 bytes.
For the code below, my array is [0]254, [1]255, [2]255, [3]0, so I can chop out byte [3]. This is on a Core i7 proc. In my production code, before the array copy, I am checking BitConverter.IsLittleEndian to determine that I can chop the last byte.
int i = 16777214;
byte[] bytesTemp = BitConverter.GetBytes(i);
byte[] value = null;
if (BitConverter.IsLittleEndian)
Array.Copy(bytesTemp, 0, value, 0, 3);
My question is - do I need to concern myself with the Endian-ness of the system, or does the CLR just use this LittleEndian format regardless? I don't have a BigEndian system (nor even know how I'd get one) to test whether my byte array comes out in the reverse order.

Yes, according to the documentation, you need to be concerned. They have an example where they reverse the bytes if the architecture is not the desired endianess.
As far as where to get a BigEndian system, I think that the ARM based processors are big-endians, although I haven't tested this. So if you're running on Win RT device or a phone, for example, you might get different behavior.

It entirely depends on what you are doing with the data. If you are going to be writing it to disk for portable persistence, then yes... I would probably care about endianness. If you are just going to use it to recreate an int later in the same process (or on the same machine), it probably doesn't matter as much.
However, when I do need to worry about endianness, I usually don't acheive that by BitConverter at all - personally, I'd be tempted to use byte masking and shifting; then you don't even need to know the endianness - it'll work the same on any system. It also avoids the annoyingly bad design decision of BitConverter returning a byte array rather than accepting an array and offset.
For example:
byte[] buffer = ...
// write little-endian
buffer[offset++] = (byte)(i & 0xFF);
buffer[offset++] = (byte)((i >> 8) & 0xFF);
buffer[offset++] = (byte)((i >> 16) & 0xFF);
buffer[offset++] = (byte)((i >> 24) & 0xFF);

Related

What is the endianess of a double on Windows 10 64bit?

I am using c# and writing a program to send numbers over UDP. I am on the Windows 10 64bit platform and I am using BitConverter in order to get the bytes from integers, doubles, etc..
As an example:
If I use:
Byte[] data = BitConverter.GetBytes((int)1);
I get, 01000000 in HEX, which would be little endian as expected.
If I use:
Byte[] data = BitConverter.GetBytes((double)1);
I get, 000000000000f03f in HEX, which looks like a big endian number but I am just not so sure.
My guess is I don't have a good understanding of endianess or of the double format. I suppose it is also possible that Windows stores doubles different from ints?
Binary representation of double is different from that of integer. It follows the ieee standard for storing floating point values. Use the ieee standard and get the binary representation of 1 and then check fir endianness.
An interesting note. As you might already know, C# doesn't define the endiannes and it depends on the cpu architecture, if you are writing cross platform/architecture applications you can check with the method call BitConverter.IsLittleEndian
Indicates the byte order ("endianness") in which data is stored in
this computer architecture.
Remarks
Different computer architectures store data using different byte
orders. "Big-endian" means the most significant byte is on the left
end of a word. "Little-endian" means the most significant byte is on
the right end of a word.
Note
You can convert from network byte order to the byte order of the host
computer without retrieving the value of the
BitConverter.IsLittleEndian field by passing a 16-bit, 32-bit, or 64
bit integer to the IPAddress.HostToNetworkOrder method.
If you need different endiannes, you can convert easily enough with Array.Reverse.
byte[] bytes = BitConverter.GetBytes(num);
Array.Reverse(bytes, 0, bytes.Length);
or bitwise switch with types like int and long, you could take it a step further with unsafe and pointers for other types
public uint SwapBytes(uint x)
{
x = (x >> 16) | (x << 16);
return ((x & 0xFF00FF00) >> 8) | ((x & 0x00FF00FF) << 8);
}
public ulong SwapBytes(ulong x)
{
x = (x >> 32) | (x << 32);
x = ((x & 0xFFFF0000FFFF0000) >> 16) | ((x & 0x0000FFFF0000FFFF) << 16);
return ((x & 0xFF00FF00FF00FF00) >> 8) | ((x & 0x00FF00FF00FF00FF) << 8);
}
Certainly little-endian.
Remember that IEEE floating-point is a bitfield, with sign having higher significance than exponent, which in turn has higher significance than mantissa.
Your integer example has only one field, and its low bits are set.
Your double example has all zero bits in the mantissa field, and the more significant field of exponent bits is non-zero. (Both of these are affected by the biasing used by IEEE-754)
The significant bits are at the higher memory addresses, just like with the little-endian integer.
For reference, IEEE-754 for 1.0 is { sign: 0, exponent: 0x3ff, mantissa: 0x0000000000000 }

C# 4 bit data type [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Does C# have a 4 bit data type? I want to make a program with variables that waste the minimum amount of memory, because the program will consume a lot.
For example: I need to save a value that i know it will go from 0 to 10 and a 4 bit var can go from 0 to 15 and it's perfect. But the closest i found was the 8 bit (1 Byte) data type Byte.
I have the idea of creating a c++ dll with a custom data type. Something like nibble. But, if that's the solution to my problem, i don't know where to start, and what i have to do.
Limitations: Creating a Byte and splitting it in two is NOT an option.
No, there is no such thing as a four-bit data type in c#.
Incidentally, four bits will only store a number from 0 to 15, so it doesn't sound like it is fit for purpose if you are storing values from 0 to 127. To compute the range of a variable given that it has N bits, use the formula (2^N)-1 to calculate the maximum. 2^4 = 16 - 1 = 15.
If you need to use a data type that is less than 8 bits in order to save space, you will need to use a packed binary format and special code to access it.
You could for example store two four-bit values in a byte using an AND mask plus a bit shift, e.g.
byte source = 0xAD;
var hiNybble = (source & 0xF0) >> 4; //Left hand nybble = A
var loNyblle = (source & 0x0F); //Right hand nybble = D
Or using integer division and modulus, which works well too but maybe isn't quite as readable:
var hiNybble = source / 16;
var loNybble = source % 16;
And of course you can use an extension method.
static byte GetLowNybble(this byte input)
{
return input % 16;
}
static byte GetHighNybble(this byte input)
{
return input / 16;
}
var hiNybble = source.GetHighNybble();
var loNybble = source.GetLowNybble();
Storing it is easier:
var source = hiNybble * 16 + lowNybble;
Updating just one nybble is harder:
var source = source & 0xF0 + loNybble; //Update only low four bits
var source = source & 0x0F + (hiNybble << 4); //Update only high bits
A 4-bit data type (AKA Nib) only goes from 0-15. It requires 7 bits to go from 0-127. You need a byte essentially.
No, C# does not have a 4-bit numeric data type. If you wish to pack 2 4-bit values in a single 8-bit byte, you will need to write the packing and unpacking code yourself.
No, even boolean is 8 bits size.
You can use >> and << operators to store and read two 4 bit values from one byte.
https://msdn.microsoft.com/en-us/library/a1sway8w.aspx
https://msdn.microsoft.com/en-us/library/xt18et0d.aspx
Depending on how many of your nibbles you need to handle and how much of an issue performance is over memory usage, you might want to have a look at the BitArray and BitVector32 classes. For passing around of values, you'd still need bigger types though.
Yet another option could also be StructLayout fiddling, ... beware of dragons though.

Representing Hex Number in a particular format in C#

I have a register which reads out the version number in the following format. It is little endian. For example:
The register value read is 0x15000000 but I need to represent this in the GUI as 00.00.00_15.
How do I print in particular format with taking care of reversal as well in C#?
You could use the BitConverter.GetBytes to get an array of bytes..
int num = 0x15000000;
var bytes = BitConverter.GetBytes(num);
// If you want your code to run even on your Big Endian fridge,
// decomment this line :)
// if (!BitConverter.IsLittleEndian) Array.Reverse(bytes);
string str = string.Format("{0:x2}.{1:x2}.{2:x2}_{3:x2}", bytes[0], bytes[1], bytes[2], bytes[3]);
and then string.Format("{num:x2}" where x2 will give an hex format of 2 digits
Note that in general, the BitConverter.GetBytes should be used only on Intel/AMD computers! If you want to make a generic code that can run anywhere, including your fridge, then it's better to use the next solution! (because your fridge could be Big Endian!)
Clearly you could do bit manipulation, shift >> and &
string str = string.Format("{0:x2}.{1:x2}.{2:x2}_{3:x2}", num & 0xFF, (num >> 8) & 0xFF, (num >> 16) & 0xFF, (num >> 24) & 0xFF);
But it's quite unreadable, unless you know a little of bit-manipulation :)
Don't treat it as a number - it's not a number. The fact that you can efficiently store it as a single int is irrelevant - just an implementation detail.
Once you start thinking in bytes in an array, you find that "little-endian" is not really anything important. Instead, you just have a structure that starts with one byte meaning one thing, the next one something else...
There's many ways to get to that behaviour, depending on where you get the actual value - taking an int will not give you control over endianness, for example. If you just take a byte[], you can do something like this:
string.Format("{0}.{1}.{2}_{3}", data[3], data[2], data[1], data[0])
This is usually very easy to handle when you're working with e.g. loading data from a file, or sending it over a socket. If you're dealing with native code interop, you can use a structure instead of int (or similar):
struct MyVersionNumber
{
byte Lowest;
byte Other;
byte YetAnother;
byte Highest;
}
Think in types - don't use primitives unless what you have is a primitive value. You're obviously working with a composite value that's (for whatever reason) folded into a primitive type. That's not a good idea for maintaining complexity :)
Once you have type, you can ensure proper type safety, validation, and just override the ToString method, for example, to output the value for the user.
Most but not all .net platforms are little endian. Therefore the correct usage of BitConverter.GetBytes is to not assume it will return one or the other.
int num = 0x15000000;
var bytes = BitConverter.GetBytes(num);
if (!BitConverter.IsLittleEndian) Array.Reverse(bytes); //it's big-endian, so reverse the bytes
string str = string.Format("{0:x2}.{1:x2}.{2:x2}_{3:x2}", bytes[0], bytes[1], bytes[2], bytes[3]);

converting 8 bytes into one long

I am currently developing a C# 2D sandbox based game. The game world is filled with tiles/blocks. Since the world is so large the game can sometimes use more than what is allowed for 32-bit application.
My tiles consist of the following data inside a struct:
public byte type;
public byte typeWall;
public byte liquid;
public byte typeLiquid;
public byte frameX;
public byte frameY;
public byte frameWallX;
public byte frameWallY;
I am looking to encapsulate all this data within one "long" (64-bit integer).
I want properties to get and set each piece of data using bit shifting, etc... (I have never done this).
Would this save space? Would it increase processing speed? If so how can it be accomplished?
Thanks.
I am looking to encapsulate all this data within one "long" (64-bit integer).
You can use StructLayoutAttribute with LayoutKind.Explicit and then decorate fields with FieldOffsetAttribute specifying the exact position.
I want properties to get and set each piece of data using bit shifting, etc... (I have never done this).
Then use shift left (<<), shift right (>>) and masking (and && to extract / or || to write (don't forget about any non-zero bits in the target byte)) with 0xff to separate individual bytes. Read more about bitwise operations here.
Would this save space? Would it increase processing speed?
Did you measure it? Did you discover a performace / memory consuption problem? If yes, go optimize it. If not, do not do premature optimizations. In other words, don't blindly try without measuring first.
I don't know why you want to do this, but you can do it in this way:
byte type = 4;
byte typeWall = 45;
byte liquid = 45;
byte typeLiquid = 234;
byte frameX = 23;
byte frameY = 23;
byte frameWallX = 22;
byte frameWallY = 221;
byte[] bytes = new [] {type, typeWall, liquid, typeLiquid, frameX, frameY, frameWallX, frameWallY};
BitConverter.ToInt64(bytes, 0);
or using << (shift) operator.
As you can see by pasting the following code into linqpad :
void Main()
{
sizeof(byte).Dump("byte size");
sizeof(Int32).Dump("int 32");
sizeof(Int64).Dump("int 64");
sizeof(char).Dump("for good measure, a char:");
}
You'll get:
byte size 1
int 32 4
int 64 8
for good measure, a char: 2
So packing 8 bytes in an int64 will be the same, but you'll have to play with the bits yourself (if that's your thing, by all means, go for it :)

Fixed/variable length structure in c# and big endian conversion

Struct {
byte F1[2]
SHORT F2
byte F3[512]
} BPD
CBD
{
SHORT CLENGTH
byte DATA[]
}
Above are 2 c++ structure. Here SHORT is of 2 byte signed.
What would be the best way to convert it into C#?
(Note that in 2nd struture length of DATA is uundefined.)
I have seen following two links.
Fixed length strings or structures in C#
and
Reading a C/C++ data structure in C# from a byte array
After reading data into structure i need to covert the short variable to big endian. (reversing bytes).
Only 'short' is needed to be converted. Array of bytes identical on big/little endian platform.
So, just read structures and do something like this:
data.F2 = ((uint)data.F2 >> 8) | ( ((uint)data.F2 & 0xFF) << 8);
and
data.CLENGTH = ((uint)data.CLENGTH >> 8) | ( ((uint)data.CLENGTH & 0xFF) << 8);
Solved myself.
Structures are good but if you are not going to modify any data classes are better to use.
I have create classes in c# for c++ structure and for big to little endian conversion i have create 3 library functions and it works for me.
Thnaks everybody for the valuable input.

Categories

Resources