3
votes

I am trying to convert integers into byte (aka unsigned char) arrays to send the array over a TCP Stream in C++ and vice versa.

I have tried many solutions on stackoverflow and own ideas but nothing really seems to work for me.

My last solution looks like this:

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include "tcpconnector.h"

typedef unsigned char byte;

using namespace std;

/*
char* byteToChar(byte* b, int length) {
    char c[length];
    for (int i = 0; i < length; i++) {
    c[i] = b[i] - 128;
    }
    return c;
}

byte* charToByte(char* c, int length) {
    byte b[length];
    for (int i = 0; i < length; i++) {
    b[i] = c[i] + 128;
    }
    return b;
}
*/

byte* intToByte(int n) {

    byte byte[4];

     byte[0] = n & 0x000000ff;
     byte[1] = n & 0x0000ff00 >> 8;
     byte[2] = n & 0x00ff0000 >> 16;
     byte[3] = n & 0xff000000 >> 24; 

     return byte;
}

int byteToInt(byte* byte) {

    int n = 0;

    n = n + (byte[0] & 0x000000ff);
    n = n + ((byte[1] & 0x000000ff) << 8);
    n = n + ((byte[2] & 0x000000ff) << 16);
    n = n + ((byte[3] & 0x000000ff) << 24);


    return n;
}

int main(int argc, char** argv)
{
    if (argc != 3) {
        printf("usage: %s <port> <ip>\n", argv[0]);
        exit(1);
    }

    int number = 42;
    byte* line = intToByte(number);

    cout << "Number: " << number << "\n";
    cout << "ArrayLength: " << sizeof line << "\n";
    cout << "Array: " << line << "\n";
    cout << "Array to Number: " << byteToInt(line) << "\n";

/*

    TCPConnector* connector = new TCPConnector();
    TCPStream* stream = connector->connect(argv[2], atoi(argv[1]));
    if (stream) {
        stream->send(byteToChar(line, 4), 4);
        delete stream;
    }

*/
    exit(0);
}

Everytime I execute this code I get the result "4202308" no matter what I set as "int number".

Any help would be appreciated.

UPDATE:

void intToByte(int n, byte* result) {

     result[0] = n & 0x000000ff;
     result[1] = n & 0x0000ff00 >> 8;
     result[2] = n & 0x00ff0000 >> 16;
     result[3] = n & 0xff000000 >> 24; 
}

Excerpt from main():

int number = 42;
byte line[4];
intToByte(number, line);

cout << "Number: " << number << "\n";
cout << "ArrayLength: " << sizeof line << "\n";
cout << "Array: " << line << "\n";
cout << "Array to Number: " << byteToInt(line) << "\n";
4
Did you determine endianness of your machine?Cherkesgiller
Hard to tell when the missing comments in your code don't show where a result array is supposed to exist - either supply its address/a reference to it as a parameter, or allocate it dynamically. Consider to change the names of the functions - at least to …Bytes…().greybeard
In this case this should be no problem as I am shifting the same bytes back and forth on the same machine. But as soon as I transfer data over the TCP Stream this could be problematic.eheller

4 Answers

3
votes

Your intToByte function is allocating a byte[4] within the scope of its body and then returning a pointer to it.

Consequently, the value is trashed as soon as your function returns and all the caller receives is a pointer to a now-invalid location - values are destroyed when they go out of scope and pointers do not extend that lifetime.

Either use a standard container object such as std::array or std::vector which your function should return to the caller or alternatively, have intToByte accept a byte[4]/byte* as an argument and fill it in.

For completeness... you could also have the function create the byte array using new, but then you'd have to remember to delete[] it, which, whilst seemingly an easy thing to do in this case, is generally bad practice when you have no good reason to make a dynamic allocation.

Additionally, the statement x & y >> z will first perform y >> z and then bitwise-AND the result with x, which is of course not what you want.

2
votes

First point: The buffer you are returning from byte* intToByte(int n) is not safe. You are returning the base address of a local array. Either pass a byte array as input or allocate the byte in heap and return the address

Second point:

Consider operator precedence.

 byte byte[4];
 byte[0] = n & 0x000000ff;
 byte[1] = ( n & 0x0000ff00 ) >> 8;
 byte[2] = ( n & 0x00ff0000 ) >> 16;
 byte[3] = ( n & 0xff000000 ) >> 24; 
2
votes

This function convert all standard type in c++ to byte vector.

template <typename T>
std::vector<byte> ToByte(T input) 
{
    byte* bytePointer = reinterpret_cast<byte*>(&input);
    return std::vector<byte>(bytePointer, bytePointer + sizeof(T));
}
0
votes

Unfortunately this is not an exact answer to your question but may be helpful. YOu can do it like in the below code I think.

#include <stdio.h>
using namespace std;

unsigned char* intToByte(const int& N) {

    unsigned char* byte = new unsigned char[4];

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

    return byte;
}


int main()
{
    unsigned char * result = intToByte(255);
    printf("%x %x %x %x\n", (unsigned char)result[0], (unsigned char)result[1],
                            (unsigned char)result[2], (unsigned char)result[3]);

    delete result;
    return 0;
}