Jump to content
  • Advertisement
Sign in to follow this  
stipperdoo

Casting values in C/C++

This topic is 4860 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am trying to figure out how to store numbers (bytes, ints, longs...) in a string or an array of chars, and read them back out again. For instance, if I can convert a long value into an array of 4 bytes, I suppose I could store the 4 bytes somewhere in an array of chars (string[]) such that string to string[i+4] could be read to reproduce the original long value. How would I do this programmatically in C/C++? ...Stip

Share this post


Link to post
Share on other sites
Advertisement
Maybe I could use memcpy in the string.h library?

Ex:

#include <string.h>
#include <stdlib.h>

int main ()
{
long* longVal;
char longBuff[4];

memcpy (longBuff, longVal, 4);
return 0;
}

Would this work? (Sorry, my C is rusty and my development environment is down.)

...Stip


Share this post


Link to post
Share on other sites
do you have any restrictions on the size of the strings cause you could store them as the number (e.g. 1234567 stored as "1234567") and just do an atol(string). if this isn't an option you could just store it as a byte[] and cast them to the values you want.

Share this post


Link to post
Share on other sites
Ugly and dirty version:

int firstint = 6;
*(int*)&string = firstint;
int secondint = *(int*)&string;

Or using memcpy :

int firstint = 6;
memcpy ( &string, &firstint, sizeof(int) );
int secondint;
memcpy ( &secondint, &string, sizeof(int) );

You would probably need to have some kind of index table to keep track of the position of each value within the string.

The big question is; Why on earth would you want to do this?? It's very very very ugly thing to do.

If you REALLY need to store values binary in a char array it would be better to store them in a struct and the cast the struct as a char array into whatever function uses it.

In any case, if the char array is ever treated as a "string" anywhere in your program you will run into problems with zeros causing your string to be cut short.

Share this post


Link to post
Share on other sites
I'd like to suggest you add what you're trying to do in general (i.e. not copy ints into a string array, but the actual problem). I agree with crudbreeder that it's ugly. Maybe if we know more we could suggest a better solution.

BTW, you might want to consider creating your own class and defining the [] operator.

Share this post


Link to post
Share on other sites
If you mean parsing strings to and from other types (including user defined types) then the standard C++ way would be to use string streams or something that uses string streams internally (like boost::lexical_cast) i.e.:


#include <sstream> // string streams
#include <string> // basic_string
#include <iostream>

int main() {

std::ostringstream oss; // output string stream

oss << "an int: " << 30434 << " float: " << 0.0343f;

std::string s = oss.str();

std::cout << s << std::endl;

}

Share this post


Link to post
Share on other sites
Quote:
Original post by crudbreeder
int firstint = 6;
*(int*)&string = firstint;
int secondint = *(int*)&string;

Keep in mind that this may crash on some processors due to misaligned data.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I think crudbreeder has the solution. I am trying to send data via winsock between a client and server. The send and recv functions take char arrays as arguments, and I need to figure out how to send chars, ints, longs, and possibly other strings back and forth. Someone gave an example of casting a struct in the networking forum. It looks like the solution I was looking for. Can anyone give me a link giving me some more information about this, or possibly some examples? Thanks.

...Stip

Share this post


Link to post
Share on other sites
Don't take offence to this, but if you don't understand basic C/C++ concepts like typecasting, you probably shouldn't be learning winsock, because it's useless until you can use it asyncronously, and for that you need either a window HWND (preferably a message only HWND), or the ability to randomly check sockets with select();

http://ensim.bkshosting.com/~admin83/w2wrap.rar

That's my winsock 2 wrapper. It's crappy, but it works and it shows you everything.

As you said, the functions do indeed take char pointers, but these pointers to data, not a string, and it doesn't have to be NULL terminated, so you can typecast anything to the char * and as long as you tell the send and recv function how big it is, no problems. For example:

struct myStruct {
int myvar;
char mystring[33];
};

(in code)

myStruct thing = { 666, "Why hello, world" };
send(mysocket, (char *)&thing, sizeof(myStruct), 0);


If you have any more problems with Winsock, email me at kawahee@gmail.com

Share this post


Link to post
Share on other sites
Quote:
Original post by snk_kid
If you mean parsing strings to and from other types (including user defined types) then the standard C++ way would be to use string streams or something that uses string streams internally (like boost::lexical_cast)



Just to expand on boost::lexical_cast:

#include <boost/lexical_cast.hpp>
#include <cassert>
#include <string>
using std::string;
using boost::lexical_cast;

int main () {
double pi_d = 3.14159265359;
string pi_s = lexical_cast< string >( pi_d );
assert( pi_s == "3.14159265359" ); //this may actually fail due to rounding errors or the like, but I'm just going to be lazy and ignore that for this example :-P

string onetwothree_s = "123";
int onetwothree_i = lexical_cast< int >( onetwothree_s );
assert( onetwothree_i == 123 );
}


Since lexical_cast uses streams internally, you can use hex specifiers, etc. and have them interpreted as desired.

EDIT: Err sorry, you mean binary data, not an actual textual conversion.

Well, I happen to have a couple of classes for pretty much just this in my library... basically, they use the shift iterator to convert an integer into either a big endian or little endian representation of the integer divided up into 4 bytes (unsigned chars), and/or said bytes back into a full integer. Here's the relevant code:

//Typedefs:
typedef unsigned long value_type; //full integer value
typedef unsigned char indexed_value_type; //sub-integer value
typedef size_t size_type;

//Common variables:
static const size_type size = size_v;
//notes: size_v == template parameter, "4" for a full 4 byte integer
indexed_value_type data[ size ];



//Big endian byte array -> Integer value
operator value_type () const {
value_type value = 0;
for ( size_type i = 0 ; i < size ; ++i ) value += data << ((size - i - 1) * CHAR_BIT);
return value;
}
//Integer value -> Big endian byte array
big_endian_integer( value_type value ) {
for ( size_type i = 0 ; i < size ; ++i ) data = (value >> ((size - i - 1) * CHAR_BIT)) & UCHAR_MAX;
}
//Little endian byte array -> Integer value
operator value_type () const {
value_type value = 0;
for ( size_type i = 0 ; i < size ; ++i ) value += data << (i * CHAR_BIT);
return value;
}
//Integer value -> Little endian byte array
little_endian_integer( value_type value ) {
for ( size_type i = 0 ; i < size ; ++i ) data = (value >> (i * CHAR_BIT)) & UCHAR_MAX;
}



I've made this code both endian-free (in the sense of processor endian) and does not do funky pointer casting which could result in crashes on 64 bit platforms.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!