2

I just need to extract those bytes using bitwise & operator. 0xFF is a hexadecimal mask to extract one byte. For 2 bytes, this code is working correctly:

#include <stdio.h>

int main()
{
    unsigned int i = 0x7ee;
    unsigned char c[2];

    c[0] = i & 0xFF;
    c[1] = (i>>8) & 0xFF;

    printf("c[0] = %x \n", c[0]);
    printf("c[1] = %x \n", c[1]);


    return 0;
}

output:

c[0] = ee;
c[1] = 7;

What should I do for 4 bytes to work correctly?

unsigned int i = 0x557e89f3;
unsigned char c[4];

my code:

unsigned char c[4];
         c[0] = i & 0xFF;
         c[1] = (i>>8) & 0xFF;
         c[2] = (i>>16) & 0xFF;
         c[3] = (i>>24) & 0xFF;
         printf("c[0] = %x \n", c[0]);
         printf("c[1] = %x \n", c[1]);
         printf("c[2] = %x \n", c[2]);
         printf("c[3] = %x \n", c[3]);
7
  • 3
    Just about the same as you do now, but shift 16 and 24 bits too. Commented Jun 15, 2015 at 8:31
  • Quite similar to this question : stackoverflow.com/questions/29862863/… I never received a better answer, but maybe my first solution is enough for you. Commented Jun 15, 2015 at 8:31
  • my output of 16 and 24 c[2] = 0 c[3] = 22 isn't work correctly Commented Jun 15, 2015 at 8:32
  • @BLUEPIXY i add my code Commented Jun 15, 2015 at 8:51
  • try unsigned long int instead of unsigned int Commented Jun 15, 2015 at 9:00

3 Answers 3

10
#include <stdio.h>

int main()
{
    unsigned int i = 0x557e89f3;
    unsigned char c[4];

    c[0] = i & 0xFF;
    c[1] = (i>>8) & 0xFF;
    c[2] = (i>>16) & 0xFF;
    c[3] = (i>>24) & 0xFF;

    printf("c[0] = %x \n", c[0]);
    printf("c[1] = %x \n", c[1]);
    printf("c[2] = %x \n", c[2]);
    printf("c[3] = %x \n", c[3]);


    return 0;
}
Sign up to request clarification or add additional context in comments.

9 Comments

@girl71 Please describe what isn't working more clearly. What is the complete input. What is the complete output.
Please check sizeof(int), in some compiler, size of integer is 16bit not 32bit, it could be a reason.
or use uint32_t (header <cstdint>) for a type with a defined number of bytes.
needles to say, format specifier might need a change, stackoverflow.com/questions/27547377/format-specifier-for-unsigned-char
@girl71 The code here: ideone.com/HX4x0W gives the proper output, so compare that with your own program. If you can't get it working, by e.g. copy pasting that code, describe in detail what kind of platform and compiler you are using.
|
1

First of all. It is not guaranteed by C standard that 'unsigned int' is 32-bit-long. To ensure it you should use uint32_t type defined in stdint.h header (C99). However, implementation of this type is not mandatory. Other solution is to use 'unsigned long' that is guaranteed to have at least 32 bits.So the solutions should be:

#include <stdio.h>

int main()

{
    unsigned long int i = 0x557e89f3UL;
    unsigned char c[4];

    c[0] = i & 0xFF;
    c[1] = (i>>8) & 0xFF;
    c[2] = (i>>16) & 0xFF;
    c[3] = (i>>24) & 0xFF;

    printf("c[0] = %x \n", c[0]);
    printf("c[1] = %x \n", c[1]);
    printf("c[2] = %x \n", c[2]);
    printf("c[3] = %x \n", c[3]);


    return 0;
}

2 Comments

uint32_t is preferred in this case. If the compiler for some reason doesn't support stdint.h, you'll need to get a new compiler, period. As a side note, the literal 0x557e89f3 is guaranteed to be unsigned and at least 32 bits wide, so the UL notation is superfluous for this specific case (although good practice in other cases).
@DonReba This is tagged both C and C++. In C (C11), unsigned int is only guaranteed to be 2 bytes long, by UINT_MAX == 65535. Not sure where you got the idea that C++ is different from C though, in C++03 18.2.2 it says: "The contents are the same as the Standard C library header <limits.h>.". Was this changed in C++11?
0

You can simply cast int* to char*. If you need the bytes in a separate array, then copy them.

#include <algorithm>
#include <iomanip>
#include <iostream>
using namespace std;

int main() {
    unsigned int i = 0x557e89f3;

    unsigned char c[4];
    copy_n((unsigned char*)&i, 4, c);

    cout << hex << (int)c[0] << ' ' << (int)c[1] << ' '
        << (int)c[2] << ' ' << (int)c[3] << endl;

    return 0;
}

It outputs the following on little-endian systems. On big-endian systems the order will be reversed.

f3 89 7e 55

6 Comments

the output of this solution depends on the endianess of the system.
@DonReba in eclipse with header<algorithm> Function 'copy_n' could not be resolved
@girl71, this function was added in C++11. If you are using gcc, it needs the -std=c++11 flag. Maybe Eclipse has an option for this. Before C++11 you would use std::copy or memcpy for this.
When it comes to serialization/de-serialization of integer types in this manner, the correct solution is always to use the shift operator. Any other solution is inferior and non-portable, and should therefore not be used.
@Lundin, no, it really depends on what you are trying to achieve. If you want to see the layout in memory, for example, then casting is the right thing to do. Let's not be dogmatic.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.