Reputation: 3928
This has been surprisingly difficult. I am extracting bits to collect information from an array of unsigned chars. There is one part I am stuck on. The array has these four bytes: 0x79,0xE8,0x39,0x1A contained in it and I need to reverse them to get 0x1A, 0x39, 0xE8, 0x79. My reverse_order function instead gives me 0x59,0x4,0x89,0x10 (which are other bytes in array):
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#define LATITUDE_OFFSET 4
#define LONGITUDE_OFFSET 5
void reverse_order(unsigned char *start, unsigned char *end)
{
int i = 4;
do {
*start = *end;
++start;
--end;
--i;
} while(i > 0);
int j;
for(j=0; j<4; j++)
{
printf("the value: 0x%x\n", start[j]);
}
}
int main(void)
{
unsigned char msg[] = {
0x28,0x83,0x63,0x20,0x79,
0xE8,0x39,0x1A,0x59,0x04,
0x89,0x10,0x8D,0x2E,0xF1,
0x11,0x6E,0x00,0x10,0x8D,
0x51,0x57,0x29,0x0D
};
unsigned long long int time_secs;
unsigned char *start, *end;
int i, j;
//remove garbage
time_secs = 0;
i = 0;
while(msg[i] == 0x28)
{
++i;
}
unsigned char resp = ((msg[i] & 0xF) * 16) + 7;
unsigned char resp2 = (msg[i] & 0xF);
++i;
int unit_id_length = ((msg[i++] & 0xC0) >> 6)+1;
int is_latitude_south = (msg[i] & 0x10) >> LATITUDE_OFFSET;
int is_longitude_west = (msg[i] & 0x20) >> LONGITUDE_OFFSET;
++i;
start = &msg[i];
i+=3;
end = &msg[i];
reverse_order(start, end);
}
Upvotes: 0
Views: 236
Reputation: 15121
Here is a fixed version of reverse_order()
based on the original version:
void reverse_order(unsigned char *start, unsigned char *end)
{
int i = 2;
int t;
do {
t = *start;
*start = *end;
*end = t;
++start;
--end;
--i;
} while(i > 0);
int j;
start -= 2;
for(j=0; j<4; j++)
{
printf("the value: 0x%x\n", start[j]);
}
}
Here is a revised version:
void
reverse(unsigned char *start, unsigned char *end)
{
unsigned char t;
while (start < end) {
t = *start;
*start = *end;
*end = t;
start++;
end--;
}
}
Upvotes: 1
Reputation: 3335
There is this nice XOR trick that allows exchanging two variables without using a temporary:
void reverse_order(unsigned char *start, unsigned char *end)
{
while (end > start) {
*start ^= *end;
*end ^= *start;
*start ^= *end;
++start;
--end;
};
}
Its probably not faster and most likely needs some comments but its always good to show how well you have learned your bitwise logic ;)
Upvotes: 0
Reputation: 206577
I found the following problems with your code:
*start
and *end
.i
by 2
in the loop. Otherwise, you will re-swap the values.start
so that it does not point to where it was when the function was called.Here's what I came up with:
void reverse_order(unsigned char *start, unsigned char *end)
{
int i = 4;
unsigned char cp;
unsigned char* iter = start;
int j;
do {
/* Swap the contents of *iter and *end */
cp = *iter;
*iter = *end;
*end = cp;
++iter;
--end;
i -= 2;
} while(i > 0);
for(j=0; j<4; j++)
{
printf("the value: 0x%x\n", start[j]);
}
}
Upvotes: 1
Reputation: 5290
Your reverse code doesn't work correctly.
Use a temporary variable:
unsigned char t = *start ;
*start = *end;
*end = t ;
You also only do half iterations, so in your case i
in the function reverse_order() would be 2
The argument end of the function is unnecessary since you have a hardcoded length of 4. Rather calculate end in the function
unsigned char* end = star + 3 ;
Upvotes: 0
Reputation: 2935
You can determine your byte ordering with the following code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
union {
short s;
char c[sizeof(short)];
}un;
un.s = 0x0102;
if (sizeof(short) == 2) {
if (un.c[0] == 1 && un.c[1] == 2)
printf("big-endian\n");
else if (un.c[0] == 2 && un.c[1] == 1)
printf("little-endian\n");
else
printf("unknown\n");
} else{
printf("sizeof(short) = %d\n", sizeof(short));
}
exit(0);
}
Upvotes: 0