Convert uint16 to byte array - c

let's say I have an array:
uint16 my_uint16_Array[6] = {0x1A20, 0x1A35, 0X1AEC, 0x1AB8, 0x1A5D, 0x1AF3}
I want to convert this array to an byte array in order to have:
uint8 my_uint8_Array[12] = {0x1A, 0x20, 0x1A, 0x35, 0X1A, 0xEC, 0x1A, 0xB8, 0x1A, 0x5D, 0x1A, 0xF3}
What is the fastest way to do it in c?

Well memcpy will not sufficient for this task on little endian machine. In that case I would do this. Although I not guarantee this is the fastest way.
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t my_uint16_Array[6] = {0x1A20, 0x1A35, 0X1AEC, 0x1AB8, 0x1A5D, 0x1AF3};
uint8_t my_uint8_Array[12];
for (int i = 0; i < 6; i++)
{
my_uint8_Array[i << 1] = my_uint16_Array[i] >> 8;
my_uint8_Array[(i << 1) + 1] = my_uint16_Array[i] & 0xFF;
}
for (int i = 0; i < 12; i++)
printf("0x%x ", my_uint8_Array[i]);
return 0;
}
Output
0x1a 0x20 0x1a 0x35 0x1a 0xec 0x1a 0xb8 0x1a 0x5d 0x1a 0xf3
Another version which seem to produce less assembly instruction with MSP430 architecture with gcc 6.2.1 and -O3 flag. Also this is somewhat closer what x86 will actually do after optimization with the above code.
#include <stdio.h>
#include <stdint.h>
int main()
{
uint16_t my_uint16_Array[6] = {0x1A20, 0x1A35, 0X1AEC, 0x1AB8, 0x1A5D, 0x1AF3};
uint8_t my_uint8_Array[12];
uint8_t *highBytePtr = (uint8_t*) my_uint16_Array;
uint8_t *lowBytePtr = (uint8_t*) my_uint16_Array;
highBytePtr++;
for (int i = 0; i < 12; i += 2, highBytePtr += 2, lowBytePtr += 2)
{
my_uint8_Array[i] = *highBytePtr;
my_uint8_Array[i + 1] = *lowBytePtr;
}
for (int i = 0; i < 12; i++)
printf("0x%x ", my_uint8_Array[i]);
return 0;
}

you can declare a uint8_t pointer and just "reinterpret" the data as a uint8_t array. But beware of endianness! the ordering may not in the way you expect it to be:
uint8_t *bytePointer = (uint8_t*) my_uint16_Array;
for(uint8_t i=0; i< sizeof(my_uint16_Array); i++) {
printf("%02X, ", bytePointer[i]);
}
On a little endian machine you get this output:
20, 1A, 35, 1A, EC, 1A, B8, 1A, 5D, 1A, F3, 1A
On a big endian machine, all value pairs are flipped:
1A, 20, 1A 35, 1A, EC, 1AB8, 1A, 5D, 1A, F3

Related

crc-16 IBM, 0x00 not taken in consideration

I did test a crc-16/ibm implementation i found on the net. when I test it with hex byte array it works fine but if I include some 0x00 values, then it doesn't give the proper result.
here is its code
unsigned short ComputeCRC16(const unsigned char* buf, unsigned int len) {
unsigned short crc = 0;
for (unsigned int j = 0; j < len; j++)
{
unsigned char b = buf[j];
for (unsigned char i = 0; i < 8; i++)
{
crc = ((b ^ (unsigned char)crc) & 1) ? ((crc >> 1) ^ 0xA001) : (crc >> 1);
b >>= 1;
}
}
return crc;
}
I tested it with this code:
int main() {
//fe b5 5f f7
unsigned char buf1[4096] = { 0xfe, 0xb5, 0x5f, 0xf7 };
//fe b5 00 5f f7 00
unsigned char buf2[4096] = { 0xfe, 0xb5, 0x00, 0x5f, 0xf7, 0x00 };
int a = strlen(buf1);
unsigned short res = ComputeCRC16(buf1, a);
printf("res = %04x\n", res); //res : 7858, the result is correct
int b = strlen(buf2);
unsigned short res = ComputeCRC16(buf2, b);
printf("res = %04x\n", res); //res : d781, the result is not correct
return 0; //the correct result : 26EE
}
to verify the result I use this website:
https://www.lammertbies.nl/comm/info/crc-calculation
Your CRC routine gives correct results. It is your test that's wrong. strlen(p) returns how many bytes there are before the first zero byte at p. For buf2, that's four, not five as you intended. For buf1 it's not even defined, since there can be anything in memory after that array. You might be getting four, if the compiler happened to put zeros after the array.
For testing, you should simply provide len manually. (buf1, 4), (buf2, 5).
By the way, that code could be more efficient. It doesn't have to test with b every time. Just exclusive-oring with b to start has the same effect:
crc ^= buf[j];
for (unsigned char i = 0; i < 8; i++)
crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;

How to concatenate the hexadecimal data in an array in C

I have my data field as follows DATA = 0x02 0x01 0x02 0x03 0x04 0x05 0x06 0x07 Now I want to concatenate this data as follows DATA = 0x01020304050607. How can I do it using C program. I found a program in C for concatenation of data in an array and the program is as follows:
#include<stdio.h>
int main(void)
{
int num[3]={1, 2, 3}, n1, n2, new_num;
n1 = num[0] * 100;
n2 = num[1] * 10;
new_num = n1 + n2 + num[2];
printf("%d \n", new_num);
return 0;
}
For the hexadecimal data in the array how can I manipulate the above program to concatenate the hexadecimal data?
You need a 64 bit variable num as result, instead of 10 as factor you need 16, and instead of 100 as factor, you need 256.
But if your data is provided as an array of bytes, then you can simply insert complete bytes, i.e. repeatedly shifting by 8 bits (meaning a factor of 256):
int main(void)
{
uint8_t data[8] = { 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
unsigned long long num = 0;
for (int i=0; i<8; i++) {
num <<=8; // shift by a complete byte, equal to num *= 256
num |= data[i]; // write the respective byte
}
printf("num is %016llx\n",num);
return 0;
}
Output:
num is 0201020304050607
Lest say you have input like
int DATA[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
If you want output like 0x0001020304050607, to store this resultant output you need one variable of unsigned long long type. For e.g
int main(void) {
int DATA[8] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
int ele = sizeof(DATA)/sizeof(DATA[0]);
unsigned long long mask = 0x00;
for(int row = 0; row < ele; row++) {
mask = mask << 8;/* every time left shifted by 8(0x01-> 0000 0001) times */
mask = DATA[row] | mask; /* put at correct location */
}
printf("%016llx\n",mask);
return 0;
}
Here's some kind of hack that writes your data directly into an integer, without any bitwise operators:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
uint64_t numberize(const uint8_t from[8]) {
uint64_t r = 0;
uint8_t *p = &r;
#if '01' == 0x4849 // big endian
memcpy(p, from, 8);
#else // little endian
for (int i=7; i >= 0; --i)
*p++ = from[i];
#endif
return r;
}
int main() {
const uint8_t data[8] = { 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
printf("result is %016llx\n", numberize(data));
return 0;
}
This does work and outputs this independently of the endianness of your machine:
result is 0201020304050607
The compile-time endianness test was taken from this SO answer.

Array of HEX Values to Decimal

I'm reading in HEX values from a file into an array.
The part of the buffer I'm using is contains 4 bytes in Hex -> CE EE 00 00
unsigned int fileLocationOffset = 64;
unsigned char fileSize[4]; //This is actually in a struct.
//Putting here for purposes of this question
unsigned char buff[sizeOfRoot];
fseek(fp, startOfRoot, SEEK_SET); //Seek to point in file fp
fread(buff, 1, sizeOfRoot, fp); //Save contents to a buffer
//Read in 4 Bytes backwards to put as Big-Endian
for(int z = 31; z > 27; z--){
fileSize[31 - z] = buff[fileLocationOffset + z];
}
//TEST: Print Values at each element to see if correct
for(int z = 0; z < 4; z++){
printf("%X ", fileSize[z]);
}
// Output: 0 0 EE CE <- Correct
So, I know that my fileSize array contains the correct values, but now I need to convert 0x00EECE to a decimal.
Could somebody please advise how I should go about doing this?
Ok, so you have the bytes of an int value in big endian order and want to build the value. You could simply place the bytes into an uint32_t variable:
uint32_t bytes_to_int(unsigned char *bytes) {
uint32_t val = 0;
for(int i=0; i<4; i++) {
val <<= 8; //shift 8 positions to the right
val |= *bytes++;
}
return val;
}
With it, the following test program:
int main() {
unsigned char foo[] = { 0, 0, 0xee, 0xce };
unsigned val = bytes_to_int(foo);
printf("%d - 0x%x\n", val, val);
return 0;
}
output as expected:
61134 - 0xeece
What do you do with the data?
Concepts like hex and decimal only apply when you print the data.
What is the output of
printf("%d", *(int *)filesize);
Your previous comment suggests you are on a little endian machine.
The value in your file is also little endian.
Why do you change your endianess?
See following test program:
// big endian
unsigned char fileSize[4] = { 0x0, 0x0, 0xEE, 0xCE };
// little endian
unsigned char fileSize2[4] = { 0xCE, 0xEE, 0x00, 0x00 };
int main(void)
{
int i;
// Output: 0 0 EE CE <- Correct
for (i = 0; i < sizeof fileSize; i++)
printf("%02x ", fileSize[i]);
printf("\n");
for (i = 0; i < sizeof fileSize2; i++)
printf("%02x ", fileSize2[i]);
printf("\n");
printf("%u\n", *(int *)fileSize);
printf("%u\n", *(int *)fileSize2);
}
Output (on pc):
00 00 ee ce
ce ee 00 00
3471704064
61134
You could extract the data as a single unsigned 32-bit integer and use that almost directly (depending on endianness issues of course).
Perhaps something like this:
uint32_t fileSize;
memcpy(&fileSize, buff[fileLocationOffset + 28], 4);
Then for the endianness issue, if you're on Linux you could use be32toh (see e.g. this endian manual page) to convert big-endian to host encoding (and it does nothing if your host system is big-endian):
fileSize = be32toh(fileSize);
The closest function to this in the Windows API is ntohl, which could be used in a similar way.
It's not hard to implement absolute byte-swapping functions, or even macros, for this:
inline uint16_t byteswap16(uint16_t value)
{
return (value & 0xff) << 8 | (value >> 8);
}
inline uint32_t byteswap32(uint32_t value)
{
return byteswap16(value & 0xffff) << 16 | byteswap16(value >> 16);
}
...
fileSize = byteswap32(fileSize);
...
Answer given by Serge Ballesta is correct, however there is one other dirty but short trick to do this.
int main() {
char data[]={0xce,0xee,0,0};
int *ptr;
ptr=data;
printf("%d\n",*ptr);
//if you want to store this result
int x=*ptr;
printf("%d\n",x);
return 0;
}
This way you won't even have to reverse your bytes.
Output:
61134
61134
Here compiler itself takes care of the endianess

4byte array convert to float(c)

void OPC_N2_data_read()
{
unsigned int32 iobyte[3][4] = {0x00, };
int32 PM_int[3] = {0x00, };
float PM[3] = {0x00, };
int8 i,j,k;
int8 mask = 0x80;
const int16 mask1 = 0x0001;
const int16 mask0 = 0x0000;
int8 trash_byte = 0x32;
output_bit(ss,1);
output_bit(PM_CLOCK_pin,0);
delay_us (1);
output_bit(ss,0);
delay_us (2);
for( i = 0 ; i < 3 ; i ++ )
{
for ( j = 0 ; j < 4 ; j ++ )
{
for (k = 0 ; k < 8 ; k ++ )
{
output_bit(PM_CLOCK_pin,1);
iobyte[i][j] = iobyte[i][j] << 1;
if ( input ( PM_MISO_pin))
{
iobyte[i][j] |= mask1;
}
else
{
iobyte[i][j] |= mask0;
}
if ((trash_byte & mask) >0)
{
output_high(PM_MOSI_pin);
}
else
{
output_bit(PM_MOSI_pin,0);
}
delay_us(1);
output_bit(PM_CLOCK_pin,0);
delay_us(5);
mask = mask >>1;
}
}
}
delay_us(3);
output_high(ss);
for(i = 0; i<3; i++)
{
PM_int[i] = ((iobyte[i][0]<<24)|(iobyte[i][1]<<16)|(iobyte[i][2]<<8)|(iobyte[i][3]));
PM[i] = *(float*)&PM_int;
}
printf ("%x%x%x%x\r\n",iobyte[0][0],iobyte[0][1],iobyte[0][2],iobyte[0][3]);
printf ("%x%x%x%x\r\n",iobyte[1][0],iobyte[1][1],iobyte[1][2],iobyte[1][3]);
printf ("%x%x%x%x\r\n",iobyte[2][0],iobyte[2][1],iobyte[2][2],iobyte[2][3]);
printf ("%lx,%lx,%lx\r\n", PM_int[0],PM_int[1],PM_int[2]);
printf ("%3.5f,%3.5f,%3.5f\r\n", PM[0],PM[1],PM[2]);
}
I receive data from a 4-byte array.
This data is a float value.
I check through the computer, I see the following.
e911bd41 d867e641 8084e941 e911bd41,d867e641,8084e941 0.00000,0.00000,0.00000
Making the four data into one INT value works fine. PM_int[0],PM_int[1],PM_int[2]
However, if you try to convert this to a float value, only 0.00000 is displayed.
I do not know where the problem is.
Looking on your source code shows that you are assuming that the received iobyte[i][0] to iobyte[i][3] shall be assumed as a float when ordering in big-endian format:
PM_int[i] = ((iobyte[i][0]<<24)|(iobyte[i][1]<<16)|(iobyte[i][2]<<8)|(iobyte[i][3]));
But if you want to convert correctly a 32bits floating-point value, you have to know if the source CPU and the destination CPU are both big-endian or little-endian. Otherwise, it is necessary to reverse the byte order before trying to convert values. So, if your target has a different endianness, replace the above code by the following:
PM_int[i] = ((iobyte[i][3]<<24)|(iobyte[i][2]<<16)|(iobyte[i][1]<<8)|(iobyte[i][0]));
In your source code, an error of the cast formatting between the float PM[i] and the 32bits integer PM_int[i] compute a bad result. The cast must be performed to the good element of the array PM_int[i].
PM[i] = *((float*)&(PM_int[i]));
Instead of:
PM[i] = *(float*)&PM_int;
With the 3 received float values {0xe9, 0x11, 0xbd, 0x41 }, {0xd8, 0x67, 0xe6, 0x41 }, {0x80, 0x84, 0xe9, 0x41 }, the output becomes:
e911bd41
d867e641
8084e941
41bd11e9,41e667d8,41e98480
23.63375,28.80070,29.18970

Flow Cytometry FCS file data segment, linear data seems skewed

final and last update (I promise)
The core of the problem is traversing the data, as Jonathan Leffler kind of alluded. The binary data is "arranged" in a matrix. For example, if I have 3 events and 4 parameters of bitwidth 8, the binary data
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
would look like
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
I have two for loops i & j, and I need to calculate the offset using that.
I initially had
(i * PAR * 2) + (j * PnB/8)
Where PAR is the number of Parameters, PnB is the bitwidth, and i is from 0 to total events and j is from 0 to PAR. This is incorrect, and not sure how I got this formula.
==
I am working on an in-house flow analysis software and am running into some issues. The FCS sample data file I am using to test the software was generated with FACSCaliber on MacOS 9 CellQuest. When I extract the data points for FSC-H and SSC-H I don't get the same results as I would on other flow software (namely FlowJo). I understand that data generated on MacOS 9 CellQuest is stored in big endian order and believe that I am correctly transforming the data as such:
for (int i = 0; i < params[j-1].PnB/8; ++i)
{
lebyte[i] = (bytes[(params[j-1].PnB/8)-1-i] & 0xff) << i*8u;
cx |= lebyte[i];
}
The code may not be elegant but it seems to do what I intend it to do with known data samples.
PnB is the bitwidth
PnR is the channel value range
The result I get when using real flow data looks correct in that the values are within the range specified by PnR, i.e. if PnR = 1024 the data stored in the 16bit space is between 0 - 1023.
However, when I plot the data I get a skewed dot plot where the scatters bend towards the FSC-H x axis.
Here is an excerpt from the FCS 3.1 Standard (Data File Standard for Flow Cytometry, International Society for Advancement of Cytometry; P. 13):
$BYTEORD/n1,n2,n3,n4/ $BYTEORD/4,3,2,1/ [REQUIRED]
This keyword specifies the endianness of the data, i.e., the byte order used to binary store numeric data values in the data set. This value of the keyword corresponds to the order from numerically least significant {1} to numerically most significant {4} in which four binary data bytes are written to compose a 32-bit word in the data acquisition computer. The numbers are separated by commas (ASCII 44). Only two distinct values are allowed:
$BYTEORD/1,2,3,4/ (little endian, i.e., least significant byte written first, e.g., x86 based personal computers)
$BYTEORD/4,3,2,1/ (big endian, i.e., least significant byte is written last, e.g., PowerPC including older Apple Macintosh computers prior to switch to Intel-based architecture)
One of these values shall be used to specify the endianness even if the size of data values exceeds 32 bits ($DATATYPE/D/)
I apologize in advance if I did not do a good job explaining and would be happy to further clarify any points as necessary. Any help will be very much appreciated.
Update
Attached image to illustrate point.
Figure 1
Update 2
I made a simplified version of the endian converter and tested it.
#include <stdio.h>
#include <stdlib.h>
int main() {
int PnB = 16; // bitwidth of data stored for a specific channel value
// for example the data value for sample A is stored in 16 bits.
char bytes[PnB/8];
unsigned int lebyte[PnB/8];
unsigned int cx = 0;
unsigned int b0, b1;
/* | [0] | [1] |
* | 0xff | 0x03 |
*/
bytes[1] = 0x03;
bytes[0] = 0xff;
// in big endian print out
b0 = (bytes[0] & 0xff) << 8u;
b1 = bytes[1] & 0xff;
cx = b0 | b1;
printf("%d\n", cx);
cx = 0;
// convert to little endian
for (int i = 0; i < PnB/8; ++i)
{
lebyte[i] = (bytes[i] & 0xff) << i*8u;
cx |= lebyte[i];
}
printf("%d\n", cx);
}
The results were correct:
65283
1023
So I made the corrections to the original source code (changes made in original post to conserve space).
Additionally I am doing memcpy to copy data over from a buffer.
memset(bytes, '\0', sizeof(char)*params[j-1].PnB/8);
memcpy(bytes, databuf+((i*data->PAR*2)+(j*params[j-1].PnB/8)), params[j-1].PnB/8);
But I still get a skewed data. It may be something to do with how the data is transformed. I just can't find any information online and I'm sure the makers of FlowJo would be unwilling to share the secret ;). I'll keep looking and see what I find.
Update 3
sorry to make it longer but additional information:
typedef struct _fcs_parameter {
double f1; // logarithmic decade
double f2; // minimum value on log scale
unsigned int PnB; // bitwidth
unsigned int PnR; // range
fcs_events *events; // event data
char *sname; // short name
char *lname; // filter name
} fcs_parameter;
Take a good hard look at the memset() and memcpy() lines you show. Since you've not shown how i is set, nor what's in your params array of structures, it's a bit hard to interpret. However, if you have any varying sizes in the PnB member, then I think your memcpy() offset calculation is bogus.
Here's some code and the output from it; you'll have to adapt it a bit to your scenario. The last section tries to emulate your memset/memcpy code, given that there's no explanation of a number of the variables you show. It includes an alternative interpretation that seems to make more sense.
You could make some of the functions into static inline, assuming you have C99. There are other bits of code that also assume C99. It's not hard to fix it to C89, but I'm not going to do that for you.
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static uint16_t convert_uint16be(uint8_t const *bytes)
{
uint16_t r = (bytes[0] << 8) | bytes[1];
return r;
}
static uint32_t convert_uint32be(uint8_t const *bytes)
{
uint32_t r = (((((bytes[0] << 8) | bytes[1]) << 8) | bytes[2]) << 8) | bytes[3];
return r;
}
static void print16(uint8_t const *bytes)
{
uint16_t r1 = convert_uint16be(bytes);
int16_t r2 = convert_uint16be(bytes);
printf("0x%.2X 0x%.2X = 0x%.4" PRIX16 " = %6" PRId16 "\n", bytes[0], bytes[1], r1, r2);
}
static void print32(uint8_t const *bytes)
{
uint32_t r1 = convert_uint32be(bytes);
int32_t r2 = convert_uint32be(bytes);
printf("0x%.2X 0x%.2X 0x%.2X 0x%.2X = 0x%.8" PRIX32 " = %11" PRId32 "\n", bytes[0], bytes[1], bytes[2], bytes[3], r1, r2);
}
int main(void)
{
int PnB = 16; // bitwidth of data stored for a specific channel value
// for example the data value for sample A is stored in 16 bits.
char bytes[PnB/8];
unsigned int lebyte[PnB/8];
unsigned int cx = 0;
unsigned int b0, b1;
/* | [0] | [1] |
* | 0xff | 0x03 |
*/
bytes[0] = 0xff;
bytes[1] = 0x03;
// in big endian print out
b0 = (bytes[0] & 0xff) << 8u;
b1 = bytes[1] & 0xff;
cx = b0 | b1;
printf("%5d = 0x%.4X\n", cx, cx);
// convert to little endian
cx = 0;
for (int i = 0; i < PnB/8; ++i)
{
lebyte[i] = (bytes[i] & 0xff) << i*8u;
cx |= lebyte[i];
}
printf("%5d = 0x%.4X\n", cx, cx);
print16((uint8_t *)bytes);
uint8_t data[] =
{
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0xFF,
0x00, 0x00, 0xFF, 0xFF,
0x08, 0x08, 0x09, 0xC0,
0x80, 0x80, 0x90, 0x0C,
0xFF, 0xFF, 0xED, 0xBC,
};
int data_size = sizeof(data) / sizeof(data[0]);
for (int i = 0; i < data_size; i += 2)
print16(&data[i]);
for (int i = 0; i < data_size; i += 4)
print32(&data[i]);
{
struct { int PnB; } params[] = { { 16 }, { 16 }, { 32 }, { 16 }, { 16 }, };
int num_params = sizeof(params) / sizeof(params[0]);
uint8_t value[4];
int i = 0;
int num = num_params;
int offset = 0;
for (int j = 1; j <= num; j++)
{
memset(value, '\0', sizeof(char)*params[j-1].PnB/8);
printf("i = %2d; j = %2d; offset = %2d; calc = %2d; size = %2d\n",
i, j, offset, ((i*7*2)+(j*params[j-1].PnB/8)), params[j-1].PnB/8);
/* The calculation works plausibly when all params[n].PnB are the same
* size, but not otherwise
*/
memcpy(value, data+((i*7*2)+(j*params[j-1].PnB/8)), params[j-1].PnB/8);
if (params[j].PnB == 16)
print16(value);
else
print32(value);
memcpy(value, data+offset, params[j-1].PnB/8);
if (params[j].PnB == 16)
print16(value);
else
print32(value);
offset += params[j-1].PnB/8;
}
}
return 0;
}
Sample output:
65283 = 0xFF03
1023 = 0x03FF
0xFF 0x03 = 0xFF03 = -253
0x00 0x00 = 0x0000 = 0
0x00 0x00 = 0x0000 = 0
0x00 0x00 = 0x0000 = 0
0x03 0xFF = 0x03FF = 1023
0x00 0x00 = 0x0000 = 0
0xFF 0xFF = 0xFFFF = -1
0x08 0x08 = 0x0808 = 2056
0x09 0xC0 = 0x09C0 = 2496
0x80 0x80 = 0x8080 = -32640
0x90 0x0C = 0x900C = -28660
0xFF 0xFF = 0xFFFF = -1
0xED 0xBC = 0xEDBC = -4676
0x00 0x00 0x00 0x00 = 0x00000000 = 0
0x00 0x00 0x03 0xFF = 0x000003FF = 1023
0x00 0x00 0xFF 0xFF = 0x0000FFFF = 65535
0x08 0x08 0x09 0xC0 = 0x080809C0 = 134744512
0x80 0x80 0x90 0x0C = 0x8080900C = -2139058164
0xFF 0xFF 0xED 0xBC = 0xFFFFEDBC = -4676
i = 0; j = 1; offset = 0; calc = 2; size = 2
0x00 0x00 = 0x0000 = 0
0x00 0x00 = 0x0000 = 0
i = 0; j = 2; offset = 2; calc = 4; size = 2
0x00 0x00 0x00 0x00 = 0x00000000 = 0
0x00 0x00 0x00 0x00 = 0x00000000 = 0
i = 0; j = 3; offset = 4; calc = 12; size = 4
0x08 0x08 = 0x0808 = 2056
0x00 0x00 = 0x0000 = 0
i = 0; j = 4; offset = 8; calc = 8; size = 2
0x00 0x00 = 0x0000 = 0
0x00 0x00 = 0x0000 = 0
i = 0; j = 5; offset = 10; calc = 10; size = 2
0xFF 0xFF 0x03 0xFF = 0xFFFF03FF = -64513
0xFF 0xFF 0x03 0xFF = 0xFFFF03FF = -64513
The problem was the formula I was using to calculate the offset.
I should have used the following:
for (int i = 0; i < data->TOT; ++i)
{
for (int j = 0; j < data->PAR; ++j)
{
// code removed for brevity
memset(bytes, '\0', sizeof(char)*params[j].PnB/8);
memcpy(bytes, databuf+((i*data->PAR*params[j].PnB/8)+(j*params[j].PnB/8)), params[j].PnB/8);
// more code here
}
}
Thanks for all your help! I wouldn't not have realized that the problem was the way I was calculating the offset if you had not mentioned the PnB problem.

Resources