-1

i want to split a 29 bit value into bytes ? how can i accomplish this in C?

unsigned long value = 0x18FEF512;

I need the output like this val=0x18, val1=FE, val2=F5 , val3=12.

How to do this using bit twidlling?

ganeshredcobra
  • 1,881
  • 3
  • 28
  • 44

3 Answers3

6

try this:

unsigned long value = 0x18FEF512;
unsigned char values[4];
values[0] = value;
values[1] = value >> 8;
values[2] = value >> 16;
values[3] = value >> 24;
printf("%02X %02X %02X %02X\n",values[0],values[1],values[2],values[3]);
mostafaTmj
  • 363
  • 4
  • 12
  • What if i want to get FEF5 in one variable then how will i do shifting? – ganeshredcobra Oct 02 '14 at 21:25
  • if you want to get that you should do it this way: unsigned short val; val = value >> 8; printf("%04X",val); – mostafaTmj Oct 02 '14 at 21:27
  • What's the need of 04X by using %X itself we gets the same value? – ganeshredcobra Oct 02 '14 at 21:32
  • when your short variable is something like 0x00F5, %X will show you "F5" but %04X will show you "00F5"... that is the difference! – mostafaTmj Oct 02 '14 at 21:36
  • Thank you :) that solves my doubt Bit Twidlling always confuses me. Can you suggest a good tutorial – ganeshredcobra Oct 02 '14 at 21:38
  • 1
    You're welcome! I know some books that are good but all of them are just distributed in my country they are not english :( They don't seem to help you much. sorry! Google that there will be a lot of good material. – mostafaTmj Oct 02 '14 at 21:45
  • ... why do people think this is the answer? It simply isnt : http://codepad.org/acD6p3rr – specializt Oct 02 '14 at 23:19
  • Because it matches the question and the OP *said* it solved the problem (both specifically in words, and by accepting this answer). It doesn't get much more clear than that. – nobody Dec 04 '14 at 16:43
2

Edit per chux comment : this mixes a little C and C++ syntax - see below

The direct way is to put your 29 bit in a long or unsigned long and do bit shifting :

unsigned long value = 0x18FEF512;
unsigned char val0, val1, val2, val3;
val0 = (unsigned char) (value & 0xFF);
value >>= 8;
val1 = (unsigned char) (value & 0xFF);
value >>= 8;
val2 = (unsigned char) (value & 0xFF);
value >>= 8;
val3 = (unsigned char) (value & 0xFF);

If you have to do many times, if can be useful to first determine endianness and then directly load bytes. For endianness :

int i = 1;
char *ix = (char *) &i;
bool bigendian = (*ix == 0);

Then

char *bytes = (char *) &value;
if (bigendian) {
    val3 = bytes[0];
    val2 = bytes[1];
    val1 = bytes[2];
    val0 = bytes[3];
}
else {
    val0 = bytes[0];
    val1 = bytes[1];
    val2 = bytes[2];
    val3 = bytes[3];
}

Edit

The above mixed C++ syntax by declaring variables all along the code when C wants them at beginning, and using unneeded casts

Here is the same as true C :

#include <stdio.h>

int main() {
    unsigned long value = 0x18FEF512;
    unsigned char val0, val1, val2, val3;
    int i = 1;
    char *ix = (char *) &i;
    char bigendian = (*ix == 0);
    char *bytes = (char *) &value;

    val0 = value & 0xFF;
    value >>= 8;
    val1 = value & 0xFF;
    value >>= 8;
    val2 = value & 0xFF;
    value >>= 8;
    val3 = value & 0xFF;
    printf("Bit shifting : %x %x %x %x\n", val0, val1, val2, val3);

    value = 0x18FEF512;

    printf("%System is %s endian", bigendian ? "big" : "little");

    if (bigendian) {
        val3 = bytes[0];
        val2 = bytes[1];
        val1 = bytes[2];
        val0 = bytes[3];
    }
    else {
        val0 = bytes[0];
        val1 = bytes[1];
        val2 = bytes[2];
        val3 = bytes[3];
    }
    printf("Endian aware byte access : %x %x %x %x\n", val0, val1, val2, val3);
}
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Why the `(unsigned char)` casts? – chux - Reinstate Monica Oct 02 '14 at 21:21
  • @chux: to avoid warnings for affecting a long to an unsigned char and possibly loosing bits. – Serge Ballesta Oct 02 '14 at 21:26
  • `val0 = (unsigned char) value & 0xFF;` first casts `value` to an `unsigned char`. Then it is promoted to `int` for the following anding with `0xFF` which is an `int`. Finally the `int` result is saved as an `unsigned char`. If anything, thought you would want `val0 = (unsigned char) (value & 0xFF);`. Isn't the warning you are concerned about a C++ issue and not C? – chux - Reinstate Monica Oct 02 '14 at 21:34
  • Note that `char*` casting is a *rare exception* to the [Strict Aliasing Requirement](http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule). One should not get in the habit of casting arbitrary pointers from one type to another to peek inside their contents. – HostileFork says dont trust SE Oct 02 '14 at 21:48
-5

What you actually were asking is how to print string-segments of a string-representation of a unsigned long value, this can be achieved in numerous ways.

At first, you will need to get the string-representation of your integral, have a look at printf and the %X format - this will get you an idea of what needs to be done (tip : there is a similar function to printf which stores the result into your own field instead of printing it to stdout)

Now you will need to split that resulting string into pieces, strtok will do exactly that. With the resulting tokens you can now fill up a new char-array and finally print it.

Good luck with your assignment, you are now equipped with the necessary knowledge.

One more thing : this has nothing to do with "bit twidding" or bit shifting. At all. Maybe there ARE ways to calculate the integral segments which are equal to the string-segments but i highly doubt anyone would willingly do the math behind it - that'd basically be "re-inventing the wheel" which doesnt even serve educational purposes ...

Brad Larson
  • 170,088
  • 45
  • 397
  • 571
specializt
  • 1,913
  • 15
  • 26
  • 2
    But you are not splitting into bytes as asked by OP ... and do you know that bit shifting are among the simplest operation for the processor, even simpler than an addition because you have no carry propagation and all can be done in the same internal processor cycle ? – Serge Ballesta Oct 03 '14 at 06:40
  • Where did you get this idea? I don't see any evidence for it. Quotes please. – nobody Dec 04 '14 at 16:44
  • I don't see how `strtok` could be used here. What delimiters do you propose? Besides, converting to string and then back to bytes is needlessly overcomplicating things. Simply perform bit shifting followed by masking and be done with it. – IInspectable May 25 '16 at 12:07