0

I'm currently trying to convert an integer into a char* in order to send it over a socket. In the receiving method I logically try to treat the char* as an integer again, but I seem to be missing something because I can't get it right.

#include <iostream>

using namespace std;

int main(int argc, char** argv) {

    int num1 = 42;          // Works
    int num2 = 100;         // Works
    int num3 = 126;         // Works
    int num4 = 517;         // Doesn't seem to work for int > 127

    char p1[sizeof(int)];
    *p1 = num1;
    char p2[sizeof(int)];
    *p2 = num2;
    char p3[sizeof(int)];
    *p3 = num3;
    char p4[sizeof(int)];
    *p4 = num4;

    void* pA = p4;
    void* pB = &num4;

    int result1 = static_cast<int>(*p1);
    int result2 = static_cast<int>(*p2);
    int result3 = static_cast<int>(*p3);
    int result4 = static_cast<int>(*p4);

    int resultV1 = *static_cast<int*>(pA);
    int resultV2 = *reinterpret_cast<int*>(p3);
    unsigned int resultV3 = static_cast<int>(*p4);
    int resultV4 = *static_cast<int*>(pB);              // Works, but I need to convert a char* into an int, not a void* into an int

    cout << "R1:        " << result1 << endl;
    cout << "Expected:  " << num1 << endl << endl;
    cout << "R2:        " << result2 << endl;
    cout << "Expected:  " << num2 << endl << endl;
    cout << "R3:        " << result3 << endl;
    cout << "Expected:  " << num3 << endl << endl;
    cout << "R4:        " << result4 << endl;
    cout << "Expected:  " << num4 << endl << endl;
    cout << "RV1:       " << resultV1 << endl;
    cout << "Expected:  " << num4 << endl << endl;
    cout << "RV2:       " << resultV2 << endl;
    cout << "Expected:  " << num4 << endl << endl;
    cout << "RV3:       " << resultV3 << endl;
    cout << "Expected:  " << num4 << endl << endl;
    cout << "RV4:       " << resultV4 << endl;
    cout << "Expected:  " << num4 << endl << endl;

    getchar();
    return 0;
}

I have absolutely no idea how to solve this problem at this point. I tried several other ways, but none of them seemed to work correctly yet. It is essential that the integer is converted into a char* first as the recv() method in the WinSock-API stores its read bytes in a buffer char-array.

Any explanations or solutions? Thanks in advance.

user694733
  • 15,208
  • 2
  • 42
  • 68
chvolkmann
  • 524
  • 2
  • 9
  • You can use `std::stringstream` for converting `char*` to `int`. – Shwetha Dec 30 '14 at 06:05
  • On most system, a `char` is 8-bit long, which can only represent -128 to 127 if it is signed, and if it is unsigned 0 to 255. Your `num4` is too large for a char to represent. – SSC Dec 30 '14 at 06:08
  • How would you suggest to fix the code? I was more or less expecting the problem to be something like that, but if I store a 4-byte int in 4 different chars, that shouldn't be a problem, should it? – chvolkmann Dec 30 '14 at 06:11
  • 1
    `*p4 = num4;` <-- I think here you mean `*reinterpret_cast(p4) = num4;` (Same for the others.) – cdhowie Dec 30 '14 at 06:17
  • see http://stackoverflow.com/questions/13145777/c-char-to-int-conversion – androidbuddy Dec 30 '14 at 06:22
  • 4
    `*p1 = num1;` should really be something like `memcpy(p1, &num1, sizeof num1);` but this is a very unsatisfactory way to transfer integers over a socket anyway, due to endianness issues. You should be using functions like `htonl()`. You can pass the address of your `int` to functions like `read()` and `write()` - you don't have to copy them to or from a `char` array first. – Crowman Dec 30 '14 at 06:25
  • cdhowie: Thanks, that was pretty much what I was looking for! - I'll take a look into Paul Griffiths' way aswell. Thanks! – chvolkmann Dec 30 '14 at 06:32

3 Answers3

1

If you don't want to use C-style pointers, perhaps you can try this.

void int2CharArr(int num, char* p1){
    p1[0] = num & 0xFF;
    p1[1] = (num >> 8) & 0xFF;
    p1[2] = (num >> 16) & 0xFF;
    p1[3] = (num >> 24) & 0xFF;
}

int charArr2Int(char* p1){
    return (p1[3] << 24) + (p1[2] << 16) + (p1[1] << 8) + p1[0];
}

void test(){
    int a = 0x12345678;
    char q[sizeof(int)];
    int2CharArr(a, q);
    int b = charArr2Int(q);
    printf("%x , %x , %x , %x\n", *q, *(q+1), *(q+2), *(q+3));
    printf("%x\n", b);
}
pwwpche
  • 621
  • 1
  • 5
  • 20
0

Sorry for my primitive syntax. Have no really good and full explanation, wait for some, but this works.

char p1[sizeof(int)];
*((int *) p1) = num1;
char p2[sizeof(int)];
*((int *) p2) = num2;
char p3[sizeof(int)];
*((int *) p3) = num3;
char p4[sizeof(int)];
*((int *) p4) = num4;

void* pA = p4;
void* pB = &num4;

int result1 = *((int *)p1);
int result2 = *((int *)p2);
int result3 = *((int *)p3);
int result4 = *((int *)p4);
Ivan Ivanov
  • 2,076
  • 16
  • 33
  • Thanks, this does in fact work! Was hoping to not use C-style conversions though, so I may use cdhowie's or PaulGriffiths' method. – chvolkmann Dec 30 '14 at 06:38
  • There was a "C" tag, so I made c solution. I think it is not right for cpp because violates some cpp rules. – Ivan Ivanov Dec 30 '14 at 06:47
-1

You could do it like this:

//to a char*
char *P2 = static_cast<char *>((void*)Tst);
//from a char *
int *S1 = static_cast<int *>((void *)P2);

However, if you are sending the same number of ints each time you send, you may want to consider sending blocks of data instead, like so:

int Data[4] ={42,100,126,517};
char *C1 = static_cast<char*>((void*)Data);
send(socket,C1, sizeof(int[4]),NULL);

and to receive: char * Buff = new char[16]; recv(socket, buff, sizeof(int[4]), 0); int Data = static_cast((void)buff); int R1 = Data[0]; int R2 = Data[1]; int R3 = Data[2]; int R4 = Data[3];

or if you are sending mixed data, but the format is the same for each transmission, use structs, like so:

struct dataBlock
{
char ID[20];
int R1;
int R2;
int R3;
int R4;
};
...
dataBlock Data = {"test\0", 57,100,127,156};
char *Buff = static_cast<char*>((void*)&Data);
send(socket, Buff, sizeof(dataBlock), 0);

and then to receive:

char *Buff = new char[sizeof(dataBlock)];
recv(socket, Buff, sizeof(dataBlock),0);
dataBlock * Data = static_cast<dataBlock*>((void*)Buff);