0
votes

I'm doing this conversion is because from a network where the data being received is an array of unsigned char[8]. Every two bytes represent a UINT16 number. I want to send these bytes through a socket however, sockets require the chars to be signed (I'm working in little-endian).

Since it is impossible to convert a unsigned char to signed char I thought I could form a UINT16 number from the two unsigned chars and then decompose the number into two signed chars.

The code I have works in situations when the UINT16 number is between [0,127] and [256,65535], but when the value is between [128,255] the first char blows up to ~4294967295 and the UINT16 is now represented as ~65535. Any explanations/solutions?

uint16_t in = 129;
cout << "input is\t" << in << endl;

char lo = in & 0xFF;
char hi = in >> 8;

printf("%u", lo);
cout << "\n" << endl;
printf("%u", hi);
cout << "\n" << endl;

uint16_t out = lo | uint16_t(hi) << 8;

cout << "out is\t" << out << endl;

The error I get when I send unsigned char[] through the socket; if I use the following initialization I can use it as an appropriate argument for the send() function through the socket (winsock). Works just fine.

char buffer[8]
for (int i= 0; i <8; i++){
 buffer[i] = 0x016; //random data
  }
send(clientSocket, buffer, 8, 0);

But if initialize the buffer as following I get an error:

unsigned char buffer[8]
for (int i=0; i < 8;i++){
 buffer[i] = 0x016; //again random data
 }
 send(clientSocket, buffer,8,0);

With the error stating:

int send (SOCKET, const char *, int, int)': cannot convert argument 2 from unsigned char[8] to const char *

1
"sockets require the chars to be signed" Sockets couldn't care less about signed versus unsigned. They just operate on bytes.user3386109
Also, the code is C++ not C.Johnny Mopp
When you say “sockets require the chars to be signed,” do you mean the routines to call to perform socket functions, like writing data, take arguments of type char *, and char is signed in your C/C++ implementation? Or do you mean something about the socket semantics require a sign bit and various negative values in the characters? The latter seems doubtful, and you would have to explain it. For the former, ignore it. char * serves as a mere vehicle for conveying data, and the signedness is irrelevant. Stick whatever bytes in want in an unsigned char [] and pass it via a char *.Eric Postpischil
Technically, (e.g.) char lo should be printed with %d instead of %u. It might be better to use unsigned char lo because of uint16_t in as the source.Craig Estey
Given that you have an array of unsigned char called buffer, you can pass it to the send function with a cast: send(sockfd, (char *)buffer, ...)user3386109

1 Answers

3
votes

[This is answered for C. OP has yet to clarify their needs for C versus C++ answers.]

To pass an array of unsigned char named buffer using the send function, which has an parameter of type of const char *, simply cast the array to the required type, as with:

send(socket, (const char *) buffer, length, flags);

In C, character types are used to deal with “raw bytes” of data (as well as being used to encode characters, an unfortunate conflation of meanings and uses), so you can send any type of data this way. The socket routines will not interpret the data according to any particular type; they will just transmit the bits without regard to any signedness. You can use the same cast without const for receiving data, as long as the data is written to the same type of object that it originally came from.

(There can be issues where the sending and receiving systems use different representations for various things, such as big-endian storage on one and little-endian storage on another or four bytes for long type on one and eight bytes on another or different padding and alignment in structures. These are separate issues unrelated to the transmission of raw data via sockets.)

(As noted by Kaz, modern APIs generally declare such parameters to be void * or const void *, and no cast is necessary when passing other object pointers to them. If you encountered some compiler warning message about this, you may be using an outdated API.)