Sign in to follow this  
Nickie

Double char to single short? Easy C++ question.

Recommended Posts

Hello!
Recently I posted a thread for my memory leaks. I managed to fix them, but I didn't want to bring the topic again so I didn't answer.
So I said: Why shoud I believe in what other software says about my program? Lets track all the allocation and dellocations. This way I'll be sure everything is alright. But if I start... hmh it would be better if I create a whole memory pool. It would be more experience for me...

[b]-[/b]Intro & reasons why I need the answer of the questions. [b]Skip[/b] if you want, I just can't ask the question without giving more information than it is needed [img]http://public.gamedev.net//public/style_emoticons/default/tongue.png[/img][b]-[/b]

[size=3]Ok I read some memory pool tutorials... I didn't understand anything so I created a fresh C++ project and started coding it. Amazing but it is behaving really well even if I overload the global new operator 0_0. I made all tests I could imagine.. The alloc time is really good is most cases, however I could make a situation which requires large amout of time. This time I started editing it to get it working better.[/size]

[size=3]All chunks from my pool need a header which saves their status. I already made an algorithm which will do the job but it requires 2 bytes header for each chunk(now I'm using one byte, and each bit has different meaning for my chunk). My new functions working with bits are using unsigned shorts as arguments/parameters. So..[/size]

[size=4][b]How do I take two bytes(chars) and convert them to a single short? (everything is unsigned)[/b][/size]
[CODE]
char a[2]; a[0] = 1; a[1] = 2;
short b = a;(!?!? how shoud I cast it)
cout << b; It shoud print 258
[/CODE]



EDIT: Didn't notice I have posted it in game programming. Sorry! Edited by Nickie

Share this post


Link to post
Share on other sites
Ohhh... Seriously.. I'm playing with bitwise oprations only in the last 48 hours. And I absolutely forgot that I can do this...
I tried the second option but I messed with the C style casting I used. And it returned me a number around 65000..
Thanks.

Share this post


Link to post
Share on other sites
The bit-wise method is arguably "safer"...but perhaps this is faster?

[source lang="cpp"]char ch[2] = { 'A', 'B' };

char *cPtr = &ch;

short sh = *((short *)cPtr);[/source]

All we're doing here is obtaining the address (pointer) of "ch". Then, in one line, we cast it to a short* and dereference it. Just a quick and easy way of doing things when you're working with simple data-types of a known, fixed size.

EDIT:

Before anyone jumps my case on this I just wanted to show the OP what goes on "under the hood". As Hodgman suggest, *reinterpret_cast<short*>(a) is probably a much cleaner way to go about things and reduces the potential of programming error. But if the OP has no idea how it works then using it won't be very helpful. And what I showed is valid in C, C++, C# and quite a few other languages other than C++. Edited by ATC

Share this post


Link to post
Share on other sites
[quote name='ATC' timestamp='1347549622' post='4979747']what I showed is valid in C, C++...[/quote]Unfortunately, you're code [i]is[/i] invalid [img]http://public.gamedev.net//public/style_emoticons/default/tongue.png[/img] [code]char ch[2] = { 'A', 'B' };
char *cPtr = ch;//correct - a T[] can decay into a T* (this is what's going on in the reinterpret_cast example)
char *cPtr = &ch;//error - cannot convert from address-of-T[] to T*
char *cPtr = &ch[0];//correct - the address of the first item will be a pointer to the start of the array
short sh = *((short *)cPtr);//this is equivalent to the reinterpret_cast above, known as a C-style cast.
// I actually prefer these C-style casts as 'reinterpret_cast' is (IMHO) ugly :)
short sh = *((short *)ch);//also correct - just folding line 1 into the cast[/code] Edited by Hodgman

Share this post


Link to post
Share on other sites
[quote name='Hodgman' timestamp='1347597721' post='4979941']
Unfortunately, you're code is invalid Posted Image
[/quote]

Say waaahhhh!? [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img]

Here, run this:

///////////////////////////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
char ch[2] = { 'A', 'B' };
char *cPtr = ch;
short sh = *((short *)cPtr);

char dst[2];
short *pSh = (short *)dst;
*pSh = sh;

cout << dst[0] << dst[1] << endl;

return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////

[b][i]Output:[/i][/b] AB

So I don't see how my code was invalid? [img]http://public.gamedev.net//public/style_emoticons/default/tongue.png[/img] </scratch head>


EDIT: Oh, were you talking about how I accidentally used an ampersand in front of the array indentifier, which would actually create a char**? Twas just a typo, but your reply was nonetheless correct; as is my above example, where I didn't make the same typo! [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

EDIT (AGAIN): BTW, did you fix that in my first post for me? ;-) Edited by ATC

Share this post


Link to post
Share on other sites
Don't do the array-cast-thing if you want your bytes to be laid out in a predefined order. It is not portable. It works on Intel-style (x86, x86-64) and other little endian machines, but will may fail on some other architectures, like big endian ARM or PowerPC. If you get your data into your bytes using it as a short, you're fine though.

The shift-operator on the other hand "knows" about endianness and will produce the correct result. You should however use unsigned char instead of char, or else very funny things may happen (shift handles negative number in a special way, preserving the sign bit, thus messing up all your nice computations). Consider this for example:

[CODE]
char y[2] = {0x00, 0x80};
std::cout << std::hex << short(y[0]) << ", " << short(y[1]) << ", " << (short(y[0]) << 8 | short(y[1]))<< std::endl;
[/CODE]

You'd expect it to print "0, 80, 80", but in reality it's more likely to print "0, ff80, ffffff80" which is not at all what you want. Do the same with unsigned data types and it will work... Edited by rnlf

Share this post


Link to post
Share on other sites
[quote name='rnlf' timestamp='1347603448' post='4979962']
You should however use unsigned char instead of char, or else very funny things may happen (shift handles negative number in a special way, preserving the sign bit, thus messing up all your nice computations).
[/quote]

Well... char is a bit strange anyways because char, signed char and unsigned char are three distinct types. A char may be signed or unsigned if not specified.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this