JohnMerlino
JohnMerlino

Reputation: 3928

reversing order of bytes in c

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

Answers (5)

Lee Duhem
Lee Duhem

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

mfro
mfro

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

R Sahu
R Sahu

Reputation: 206577

I found the following problems with your code:

  1. You need to swap the values of *start and *end.
  2. You need to decrement i by 2 in the loop. Otherwise, you will re-swap the values.
  3. By the time you are printing the values, you have already incremented 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

this
this

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

PersianGulf
PersianGulf

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

Related Questions