tags:

views:

146

answers:

5

Is this possible? I wanted to convert this into a char* so I could later retrieve this values.

+4  A: 

Sure:

int array[4] = {1, 2, 3, 4};
char* c = reinterpret_cast<char*>(array);

The valid range is from c to c + sizeof(array). You are allowed to do this to any POD type.

You can cast back from a sequence of bytes:

// assuming c above
int (&pArray)[4] = *reinterpret_cast<int(*)[4]>(c);

This is guaranteed to work. But, it seems you're trying to send stuff across a network, which can introduce other problems


The process you're looking for is called serialization (and has a FAQ entry). This is when you take an object, transform it into a series of bits, which can later be "deserialized" into the original object.

Making this work across multiple platforms can be tricky, because you need to make sure you serialize into a specific format, and that each platform knows how it should read from that format. (For example, a big-endian platform might always convert to little-endian before sending, and likewise convert back to big-endian when receiving.) You cannot treat non-POD types as a stream of bytes (such as std::string), so you need to write serialization functions for those, to transform their data into a stream of bytes, and deserialization functions to transform it back.

I particularly like that way Boost does this, and if you can I'd use their serialization library. They basically first define routines for serializing fundamental types, then you can serialize more complex types by building off that. Of course, Boost also has their ASIO library to do sockets for you.

GMan
Ideally the last element in the array would be a zero in case someone down the line passes the char* to a str* function
hamishmcn
That intention isn't explicitly stated in the question though.
George Edison
This seemed to have worked, but just wondering- how do I get the actual data from it? For example, if I printed this out, it actually gave me a smiley face symbol (=D)- I'm guessing that's what 1234 represents or something. Can I actually disassembles this back into 1,2,3,4?
seed
@seed: if it prints a smiley, that means that the last byte of the first int (assuming little-endian) equals the DOS character value for the smiley.
George Edison
So can I convert this back?
seed
@George Edison: It prints a smiley? Awesome! I'm going to try this out now! :)
FrustratedWithFormsDesigner
@Frustrated: Haha, it totally does print a smiley. I'm badass and clearly planned this out.
GMan
So I have to deserialize this data and I'll be alright?
seed
No, you're pretty much asking for trouble if you're trying to serialize or deserialize. If that's what you want, go read up on `snprintf` and `sscanf`.
Mike DeSimone
Okay, so what other options do I have?
seed
@seed: not too many other options. As @Mike mentioned, you should look into `sprintf`.
George Edison
I tried `int (` that Gman added, and I guess I can't really test it with printf, which is what I'm using, because I always have to convert it to a char anyways.
seed
I _think_ that the cast `char* -> int[4]` is only valid if the `char*` was obtained from a cast `int[4] -> char*`. Otherwise it doesn't obey the strict aliasing rules (e.g., if you read an array of bytes from a file, you can't just cast the `char*` obtained from the file into an `int[4]`, you have to cast the `int[4]` to a `char*` and then copy the bytes from the file into the `int[4]`).
James McNellis
That's what I'm doing, no? I'm converting an int[] to char, then back to int[].
seed
@seed: Yes; I just wanted to clarify. Maybe I just made it more confusing... I'm good at doing that.
James McNellis
A: 

This what you're looking to do?

int list[5] = {1,2,3,4,5};

char * pChar = (char *)list;
George Edison
A: 

You can use C-style, but in C++:

int arr[] = {0, 1, 2, 3, 4};
char* p_arr = reinterpret_cast<char*>(arr);
AraK
+3  A: 

Yes, but you probably shouldn't.

Doing so will treat the ints as sequences of bytes. It is tempting to then pass these bytes to be written to files or across sockets. The problem is that that the result will not be portable. There is no guarantee that whatever computer reads those bytes will interpret them in the same way. The biggest issue is big-endian vs little-endian. Essentially, some computers put the most significant byte first whereas others put the least significant byte first. Switching between them will result in the number being read backwards.

Winston Ewert
Ah yes, I read about this.... while I guess it is a very bad idea, I'll just try it, it's more of an experiment than something that'll go on the market ;)
seed
A: 

If you want a string, use std::string, not char*. If you want serialization, use <stringstream>.

#include <stringstream>

std::ostringstream packet_os;
for ( int i = 0; i < 5; ++ i ) packet_os << arr[ i ] << " ";
network_send( packet_os.str().c_str() ); // c_str() returns char*

On the other end:

network_receive( recv_buf );
std::istringstream packet_is( recv_buf->bytes );
for ( int i = 0; i < 5; ++ i ) packet_is >> arr[ i ];
assert ( packet_is ); // for debugging, check that everything was received OK
Potatoswatter
The params for a function only accept char*
seed
@seed: sorry, I was writing a code comment as you wrote your question comment.
Potatoswatter
Okay, I see. (Not enough chars so I'll put this in).
seed
@seed: Especially considering "The params for a function only accept char*", this would seem to completely answer your question. Is that not the case?
Potatoswatter
@potatoswatter- Yeah, but I think I just need a way of turning it back.
seed
@seed: see update.
Potatoswatter
@potatoswatter- I'm guessing network_send is pseudo function?
seed
@seed: right, in the absence of any other kind of specification.
Potatoswatter
@potatoswatter- I think it's either the console or maybe the network which messes up this data, so I've opened a new thread directly related to networking. Thanks for the help though!
seed