Converting an int into a 4 byte char array (C)

后端 未结 10 2140
北荒
北荒 2020-11-27 10:07

Hey, I\'m looking to convert a int that is inputed by the user into 4 bytes, that I am assigning to a character array. How can this be done?

Example:

Convert

相关标签:
10条回答
  • 2020-11-27 10:26

    Why would you need an intermediate cast to void * in C++ Because cpp doesn't allow direct conversion between pointers, you need to use reinterpret_cast or casting to void* does the thing.

    0 讨论(0)
  • 2020-11-27 10:26

    An int is equivalent to uint32_t and char to uint8_t.

    I'll show how I resolved client-server communication, sending the actual time (4 bytes, formatted in Unix epoch) in a 1-bit array, and then re-built it in the other side. (Note: the protocol was to send 1024 bytes)

    • Client side

      uint8_t message[1024];
      uint32_t t = time(NULL);
      
      uint8_t watch[4] = { t & 255, (t >> 8) & 255, (t >> 16) & 255, (t >> 
      24) & 255 };
      
      message[0] = watch[0];
      message[1] = watch[1];
      message[2] = watch[2];
      message[3] = watch[3];
      send(socket, message, 1024, 0);
      
    • Server side

      uint8_t res[1024];
      uint32_t date;
      
      recv(socket, res, 1024, 0);
      
      date = res[0] + (res[1] << 8) + (res[2] << 16) + (res[3] << 24);
      
      printf("Received message from client %d sent at %d\n", socket, date);
      

    Hope it helps.

    0 讨论(0)
  • 2020-11-27 10:28

    The portable way to do this (ensuring that you get 0x00 0x00 0x00 0xaf everywhere) is to use shifts:

    unsigned char bytes[4];
    unsigned long n = 175;
    
    bytes[0] = (n >> 24) & 0xFF;
    bytes[1] = (n >> 16) & 0xFF;
    bytes[2] = (n >> 8) & 0xFF;
    bytes[3] = n & 0xFF;
    

    The methods using unions and memcpy() will get a different result on different machines.


    The issue you are having is with the printing rather than the conversion. I presume you are using char rather than unsigned char, and you are using a line like this to print it:

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

    When any types narrower than int are passed to printf, they are promoted to int (or unsigned int, if int cannot hold all the values of the original type). If char is signed on your platform, then 0xff likely does not fit into the range of that type, and it is being set to -1 instead (which has the representation 0xff on a 2s-complement machine).

    -1 is promoted to an int, and has the representation 0xffffffff as an int on your machine, and that is what you see.

    Your solution is to either actually use unsigned char, or else cast to unsigned char in the printf statement:

    printf("%x %x %x %x\n", (unsigned char)bytes[0],
                            (unsigned char)bytes[1],
                            (unsigned char)bytes[2],
                            (unsigned char)bytes[3]);
    
    0 讨论(0)
  • 2020-11-27 10:30

    The problem is arising as unsigned char is a 4 byte number not a 1 byte number as many think, so change it to

    union {
    unsigned int integer;
    char byte[4];
    } temp32bitint;
    

    and cast while printing, to prevent promoting to 'int' (which C does by default)

    printf("%u, %u \n", (unsigned char)Buffer[0], (unsigned char)Buffer[1]);
    
    0 讨论(0)
  • 2020-11-27 10:31

    In your question, you stated that you want to convert a user input of 175 to 00000000 00000000 00000000 10101111, which is big endian byte ordering, also known as network byte order.

    A mostly portable way to convert your unsigned integer to a big endian unsigned char array, as you suggested from that "175" example you gave, would be to use C's htonl() function (defined in the header <arpa/inet.h> on Linux systems) to convert your unsigned int to big endian byte order, then use memcpy() (defined in the header <string.h> for C, <cstring> for C++) to copy the bytes into your char (or unsigned char) array.

    The htonl() function takes in an unsigned 32-bit integer as an argument (in contrast to htons(), which takes in an unsigned 16-bit integer) and converts it to network byte order from the host byte order (hence the acronym, Host TO Network Long, versus Host TO Network Short for htons), returning the result as an unsigned 32-bit integer. The purpose of this family of functions is to ensure that all network communications occur in big endian byte order, so that all machines can communicate with each other over a socket without byte order issues. (As an aside, for big-endian machines, the htonl(), htons(), ntohl() and ntohs() functions are generally compiled to just be a 'no op', because the bytes do not need to be flipped around before they are sent over or received from a socket since they're already in the proper byte order)

    Here's the code:

    #include <stdio.h>
    #include <arpa/inet.h>
    #include <string.h>
    
    int main() {
        unsigned int number = 175;
    
        unsigned int number2 = htonl(number);
        char numberStr[4];
        memcpy(numberStr, &number2, 4);
    
        printf("%x %x %x %x\n", numberStr[0], numberStr[1], numberStr[2], numberStr[3]);
    
        return 0;
    }
    

    Note that, as caf said, you have to print the characters as unsigned characters using printf's %x format specifier.

    The above code prints 0 0 0 af on my machine (an x86_64 machine, which uses little endian byte ordering), which is hex for 175.

    0 讨论(0)
  • 2020-11-27 10:32

    You can try:

    void CopyInt(int value, char* buffer) {
      memcpy(buffer, (void*)value, sizeof(int));
    }
    
    0 讨论(0)
提交回复
热议问题