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

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 a user inputs of 175 to

00000000 00000000 00000000 10101111


Issue with all of the answers so far, converting 255 should result in 0 0 0 ff although it prints out as: 0 0 0 ffffffff

unsigned int value = 255;   

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

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

temp32bitint.integer = value;
buffer[8] = temp32bitint.byte[3];
buffer[9] = temp32bitint.byte[2];
buffer[10] = temp32bitint.byte[1];
buffer[11] = temp32bitint.byte[0];

both result in 0 0 0 ffffffff instead of 0 0 0 ff

Just another example is 175 as the input prints out as 0, 0, 0, ffffffaf when it should just be 0, 0, 0, af

This question is related to c

The answer is


You can try:

void CopyInt(int value, char* buffer) {
  memcpy(buffer, (void*)value, sizeof(int));
}

int a = 1;
char * c = (char*)(&a); //In C++ should be intermediate cst to void*

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.


You can simply use memcpy as follows:

unsigned int value = 255;
char bytes[4] = {0, 0, 0, 0};
memcpy(bytes, &value, 4);

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.


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]);

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.


Do you want to address the individual bytes of a 32-bit int? One possible method is a union:

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

int main()
{
    foo.integer = 123456789;
    printf("%u %u %u %u\n", foo.byte[3], foo.byte[2], foo.byte[1], foo.byte[0]);
}

Note: corrected the printf to reflect unsigned values.


The issue with the conversion (the reason it's giving you a ffffff at the end) is because your hex integer (that you are using the & binary operator with) is interpreted as being signed. Cast it to an unsigned integer, and you'll be fine.