0

I am new to c-programming, and am working with socket programming. I and want to store values from a char* buffer to different variables, but I'm having troubles storing int-values.

The data I have received from the socket is in binary and is saved in a char* buffer, using recv(). The first 3 bytes of the buffer will be saved in three different unsigned char variables, this works fine by doing:

unsigned char first = buffer[0];
unsigned char second= buffer[1];
unsigned char third = buffer[2];

Now my problem rises. I want to save the next bytes in two int variables (4 bytes each). Now I have tried:

unsigned int fourth= buffer[3];
unsigned int fifth= buffer[7];

The fourth variable holds the number 83, which is expected. However, the fifth variable is expected to be the number 1000, but what I get is 232. What am I missing here?

avp
  • 21
  • 2
  • At least show in your question the content of the character buffer, – Vlad from Moscow May 04 '21 at 12:51
  • 3
    Did you already learn about multi-byte values? You need to calculate the integers according to the endianness of the binary data. – the busybee May 04 '21 at 12:51
  • 1
    I guess this was already [answered here](https://stackoverflow.com/questions/27700344/converting-a-char-into-an-int). But as OP asks why he gets 232 instead of 1000 : `unsigned int fifth= buffer[7];` means to assign the char value ( a byte) from `buffer[7]` to variable `fifth` on the stack. As decimal 1000 is 0x3E8 in hexadecimal and as the data are stored the [little endian](https://en.wikipedia.org/wiki/Endianness) way, you have 0xE8 (232 decimal) in `buffer[7]`and 0x3 in `buffer[8]`, 0x0 in `buffer[9]` and `buffer[10]`. – Zilog80 May 04 '21 at 13:03
  • The `unsigned int fifth= buffer[7];`doesn't take the four bytes from `buffer[7..10]`, it takes only the value of `buffer[7]` and stores it as an int into `fifth`. See the question linked to see how to get your int value. – Zilog80 May 04 '21 at 13:03
  • 1
    "am working with socket programming" Then what's the network endianess of the protocol used and the CPU endianess of your client? – Lundin May 04 '21 at 13:33

3 Answers3

1

You have three ways:

unsigned int fourth
unsigned int fifth;
  1. If endianess are the same
memcpy(&fourth, &buffer[3], sizeof(fourth));
memcpy(&fifth, &buffer[7], sizeof(fifth));

or you can use unions.

  1. More universal way (but you still need to know how the data is stored in the buffer)

If buffer stores the least important byte first (little endian):

fourth = buffer[3] + (((unsigned int)buffer[4]) << 8) + (((unsigned int)buffer[5]) << 16) + (((unsigned int)buffer[6]) << 24)

If buffer stores the least important byte last (big endian):

fourth = buffer[6] + (((unsigned int)buffer[5]) << 8) + (((unsigned int)buffer[4]) << 16) + (((unsigned int)buffer[3]) << 24)
0___________
  • 60,014
  • 4
  • 34
  • 74
1

What am I missing here?

You are missing that unsigned int fourth= buffer[3]; will only read 1 out of the 4 bytes that you want. To get the correct value, you need to read and use buffer[3], buffer[4], buffer[5], buffer[6]. In order to get integer value, you need to apply proper bit shifting and add things together.

When data is exchange over a network, data are (aka should always be) send in "network order". The host may use a different byte order. So first convert the 4 bytes to a "network order" unsigned 32 bit integer and then convert to the host order.

uint32_t network_uint32 = ((unsigned int)buffer[3] << 24) +
                          ((unsigned int)buffer[4] << 16) +
                          ((unsigned int)buffer[5] <<  8) +
                           (unsigned int)buffer[6];
uint32_t host_uint32 = ntohl(network_uint32);

In this way your code will work on both little and big endian hosts.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
0

the answer is already given, so let's just see why you got 252 instead of 1000;


Firstly, let's see the memory:

if you convert your decimal values into hex (because System stores in hex format)


83 (dec) == 53(hex), this stored in the memory like this: 53 00 00 00(little endian).

1000(dec) == 3e8(hex), this one is stored as: e8 03 00 00.

enter image description here


So,


when you do:
unsigned int fourth = buffer[3];

It is not actually getting 4 bytes, but its getting only 1 byte which is 53 at index 3;
here:

53(hex) == 83(dec) that's why you got an expected value;


but when you are doing this part:
unsigned int fifth = buffer[7];

as above this is getting only e8 at index 7, but not 4bytes;
here:

e8(hex) == 232(dec), and that's why your fifth value is giving you 232.

Zrn-dev
  • 99
  • 5