VBA - Get Long Integer into Byte Array? - arrays

I'm trying to get a random number Long Int (4 bytes) into the last 4 bytes of a byte array (Dim MybyteArray (1 to 16) As Byte). Can't see a simple way to do this. Any ideas?

Windows uses little endian data. Each byte is normal, big to leftmost and small to rightmost. But the bytes are in reverse order. by LSBit to MSBit
00000000, 11111111, 22222222, 33333333
LSByte MSByte
Or In Hex
&h01, &h23, &h45, &h67 = &h67452301
Intel uses Little endian and Motorola uses big endian.

Related

fread and endianness confusion

So to provide context, my system is little endian and the file that I am reading from is big endian (MIDI format, for those that are interested). I am supposed to read a variety of data from the file, including unsigned integers (8 bit, 16 bit, and 32 bit), chars, and booleans.
So far I know that reading unsigned integers will be an issue with fread() because I would have to convert them from big endian to little endian. My first question is, although maybe stupid to some, do I need to convert chars and booleans as well?
My second question is regarding the entire file format. Since the file is in a different endian system, do I need to read the file from the end towards the beginning (since the MSB and LSB positions will be different)? Or do I need to read in the values from the start to the end, like I would normally, and then convert those to little endian?
Thanks for taking the time to read my post and for any answers that I might receive!
Endianness only reverses order inside words of a certain length, usually 2, 4, or 8 bytes. If you're reading in a one byte value such as a char or a bool, then endianness has no effect. However, if you're reading in any value that is more than a byte, such as an integer, then endianness matters. You can still use fread since endianness has nothing to do with file reading, just make sure to convert from big endian to little endian.
When you read external data that isn't just a sequence of characters, you read it as a sequence of bytes, and construct the actual data that you want from it.
If you expect a signed 16 bit number, followed by an unsigned 8 bit number, followed by an unsigned 32 bit number, you write a function reading two bytes and returns them converted to a signed 16 bit number, one that reads one byte and returns it as an unsigned 8 bit number, and one that reads four bytes and returns them converted to a 32 bit number. Construct the 16 and 32 bit numbers using bit shifting.

Determining the hexadecimal values of an address of a little endian machine

I am a bit confused on how you would approach this problem:
Consider decimal number 1027. This value is stored as a 16-bit two's complement number into addresses 124 and 125 on a little endian machine which has an addressable cell size of one byte. What values (in hexadecimal) are in each of these addresses:
124:
125:
I know that a little endian machine orders it addresses from the least significant byte to the most significant byte. But besides from that I am unsure of how you would apply that concept and how you would order bytes into the addresses.
Here's some simple Python code to convert that integer to little-endian hexadecimal representation:
# convert the integer (1027) to hex using 2 bytes and little-endian byteorder
(1027).to_bytes(length=2, byteorder='little').hex()
This gives 0304. So, the first byte (03) is in address 124 and the second one (04) occupies the next address - 125.
"Little endian" and "big endian" relate to how the machine multiplexes bytes from memory into registers of the CPU.
With each byte it gets, it increments the address counter, but does it place these bytes from left-to-right or right-to-left into the register?
So the address that gets loaded into a machine register (or an integer), can be stored reverse in the memory. Even with modern CPUs with broad data busses, the concept remained and in some CPUs the bytes get swapped inside the CPU.

Binary notation and Endianness

Can we say that our 'traditional' way of writing in binary
is Big Endian?
e.g., number 1 in binary:
0b00000001 // Let's assume its possible to write numbers like that in code and b means binary
Also when I write a constant 0b00000001 in my code, this will always refer to integer 1 regardless if machine is big endian or little endian right?
In this notation the LSB is always written as the last element from the right, and MSB is always written as the left most element right?
Yes, humans generally write numerals in big-endian order (meaning that the digits written first have the most significant value), and common programming languages that accept numerals interpret them in the same way.
Thus, the numeral “00000001” means one; it never means one hundred million (in decimal) or 128 (in binary) or the corresponding values in other bases.
Much of C semantics is written in terms of the value of a number. Once a numeral is converted to a value, the C standard describes how that value is added, multiplied, and even represented as bits (with some latitude regarding signed values). Generally, the standard does not specify how those bits are stored in memory, which is where endianness in machine representations comes into play. When the bits representing a value are grouped into bytes and those bytes are stored in memory, we may see those bytes written in different orders on different machines.
However, the C standard specifies a common way of interpreting numerals in source code, and that interpretation is always big-endian in the sense that the most significant digits appear first.
If you want to put it that way, then yes, we humans write numerals in Big-Endian order.
But I think you have a misunderstanding in terms of your target runnign with big or little endian.
In your actual C-Code, it does not matter which endianess your target machine uses. For example these lines will always display the same, no matter the endianess of your system:
uint32 x = 0x0102;
printf("Output: %x\n",x); // Output: 102
or to take your example:
uint32 y = 0b0001;
printf("Output: %d\n",y); // Output: 1
However the storage of the data in your memory differs between Little and Big Endian.
Big Endian:
Actual Value: 0x01020304
Memory Address: 0x00 0x01 0x02 0x03
Value: 0x01 0x02 0x03 0x04
Little Endian:
Actual Value: 0x01020304
Memory Address: 0x00 0x01 0x02 0x03
Value: 0x04 0x03 0x02 0x01
Both times the actualy value is 0x01020304 (and this is what you assign in your C-Code).
You only have to worry about it, if you do memory operations. If you have a 4-Byte (uint8) array, which represents a 32-Bit integer and you want to copy it into a uint32 variable you need to care.
uint8 arr[4] = {0x01, 0x02, 0x03, 0x04};
uint32 var;
memcpy(&var,arr,4);
printf("Output: %x\n",var);
// Big Endian: Output: 0x01020304
// Little Endian: Output: 0x04030201

Why does the struct in this union appear to order itself backwards

#include <stdio.h>
union bits_32{
unsigned int x;
struct {char b4,b3,b2,b1;} byte;
} ;
int main(int argc, char **argv){
union bits_32 foo;
foo.x=0x100000FA;
printf("%x",foo.byte.b4 & 0xFF);
}
This will output FA. Why doesn't it output 10 since b4 occupies the first space?
It's depends on endianess of your machine. If your machine is little endian it prints FA(Your's is little endian right?). If your machine is big endian it prints 10.
Storing Words in Memory
We've defined a word to mean 32 bits. This is the same as 4 bytes. Integers, single-precision floating point numbers, and MIPS instructions are all 32 bits long. How can we store these values into memory? After all, each memory address can store a single byte, not 4 bytes.
The answer is simple. We split the 32 bit quantity into 4 bytes. For example, suppose we have a 32 bit quantity, written as 90AB12CD16, which is hexadecimal. Since each hex digit is 4 bits, we need 8 hex digits to represent the 32 bit value.
So, the 4 bytes are: 90, AB, 12, CD where each byte requires 2 hex digits.
It turns out there are two ways to store this in memory.
Big Endian
In big endian, you store the most significant byte in the smallest address. Here's how it would look:
Address Value
1000 90
1001 AB
1002 12
1003 CD
Little Endian
In little endian, you store the least significant byte in the smallest address. Here's how it would look:
Address Value
1000 CD
1001 12
1002 AB
1003 90
Notice that this is in the reverse order compared to big endian. To remember which is which, recall whether the least significant byte is stored first (thus, little endian) or the most significant byte is stored first (thus, big endian).
Notice I used "byte" instead of "bit" in least significant bit. I sometimes abbreciated this as LSB and MSB, with the 'B' capitalized to refer to byte and use the lowercase 'b' to represent bit. I only refer to most and least significant byte when it comes to endianness.

How are the values stored in the C unsigned shorts?

I'm trying to read a binary file into a C# struct. The file was created from C and the following code creates 2 bytes out of the 50+ byte rows.
unsigned short nDayTimeBitStuffed = atoi( LPCTSTR( strInput) );
unsigned short nDayOfYear = (0x01FF & nDayTimeBitStuffed);
unsigned short nTimeOfDay = (0x01F & (nDayTimeBitStuffed >> 9) );
Binary values on the file are 00000001 and 00000100.
The expected values are 1 and 2, so I think some bit ordering/swapping is going on but not sure.
Any help would be greatly appreciated.
Thanks!
The answer is 'it depends' - most notably on the machine, and also on how the data is written to the file. Consider:
unsigned short x = 0x0102;
write(fd, &x, sizeof(x));
On some machines (Intel), the low-order byte (0x02) will be written before the high-order byte (0x01); on others (PPC, SPARC), the high-order byte will be written before the low-order one.
So, from a little-endian (Intel) machine, you'd see the bytes:
0x02 0x01
But from a big-endian (PPC) machine, you'd see the bytes:
0x01 0x02
Your bytes appear to be 0x01 and 0x04. Your calculation for 0x02 appears flawed.
The C code you show doesn't write anything. The value in nDayOfYear is the bottom 9 bits of the input value; the nTimeOfDay appears to be the next 5 bits (so 14 of the 16 bits are used).
For example, if the value in strInput is 12141 decimal, 0x2F6D, then the value in nDayOfYear would be 365 (0x16D) and the value in nTimeOfDay would be 23 (0x17).
It is a funny storage order; you can't simply compare the two values whereas if you packed the day of year in the more significant portion of the value and time into the less significant, then you could compare values as simple integers and get the correct comparison.
The expected file contents are very much related to the processor and compiler used to create the file, if it's binary.
I'm assuming a Windows machine here, which uses 2 bytes for a short and puts them in little endian order.
Your comments don't make much sense either. If it's two bytes then it should be using two chars, not shorts. The range of the first is going to be 1-365, so it definitely needs more than a single byte to represent. I'm going to assume you want the first 4 bytes, not the first 2.
This means that the first byte will be bits 0-7 of the DayOfYear, the second byte will be bits 8-15 of the DayOfYear, the third byte will be bits 0-7 of the TimeOfDay, and the fourth byte will be bits 8-15 of the TimeOfDay.

Resources