Jump to content
  • Advertisement
Sign in to follow this  
Nickie

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

This topic is 2203 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

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...

-Intro & reasons why I need the answer of the questions. Skip if you want, I just can't ask the question without giving more information than it is needed tongue.png-

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.

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..

How do I take two bytes(chars) and convert them to a single short? (everything is unsigned)

char a[2]; a[0] = 1; a[1] = 2;
short b = a;(!?!? how shoud I cast it)
cout << b; It shoud print 258




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
Advertisement
[font=courier new,courier,monospace]short b = short(a[0])<<8 | short(a[1]);[/font]
or
[font=courier new,courier,monospace]short b = *reinterpret_cast<short*>(a);[/font]

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
what I showed is valid in C, C++...
Unfortunately, you're code is invalid tongue.png 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
Edited by Hodgman

Share this post


Link to post
Share on other sites

Unfortunately, you're code is invalid Posted Image


Say waaahhhh!? biggrin.png

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;
}

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

Output: AB

So I don't see how my code was invalid? tongue.png </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! smile.png

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
Your first post had a typo:
1) [font=courier new,courier,monospace]char *cPtr = &ch;[/font]
vs
2) [font=courier new,courier,monospace]char *cPtr = ch;[/font]

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:


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


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

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).


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
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!