Link to home
Create AccountLog in
Avatar of BooBoo1025
BooBoo1025

asked on

How to get 4 bytes from an unsigned char pointer and convert to int?

Hi Guys,
   I have code like this:

unsigned char *pBuff;

pBuff is assigned to something;

Now, I want to get the first 4 bytes from that pBuff and save it as an int type, i.e. :

int iValue = // the first 4 bytes from pBuff;

How do I do it please?

Thanks,
BB
ASKER CERTIFIED SOLUTION
Avatar of rstaveley
rstaveley
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Avatar of BooBoo1025
BooBoo1025

ASKER

well, my pBuff can be more than 32-bit and I only want to get the 4 bytes from where it is pointing to.
it might be possable to say:

unsigned char *pBuff;
int iValue;

for (int I=0;I<4:i++){
 iValue=*pBuff[I]
}

try that and see what happens
Dawaffleman,
     If I do that, then I will get the fourth element from the pBuff, which is not what I want.
well if each element was one byte which a character is (correct?) then it should get the fourth byte, or charater
but the fourth byte is different than 4 bytes. I want to be able to get all 4 bytes.
oh i see, my mistake heh.

well then maybe you could make a union... i dont know the EXACT syntax becuase ive never had to use it, but it goes something like this

union myUnion{
int myVal;              //four bytes
char byte1;          //first of four bytes
char byte2;           //second
char byte3;          //third
char byte4;           //fourth
};

then you could go:

myUnion myValue;
myValue.byte1=*pBuff[0];
myValue.byte2=*pBuff[1];
myValue.byte3=*pBuff[2];
myValue.byte4=*pBuff[3];

that should work, theoretically. if you dont know what a union is its basically a structure, but more compact. the size of the union is the size of the largest member (in this case int). the other values will then share this same data space for thier own values. remember that i dont know if thats exactly what you need but i would guess it would be something very close to that.




Avatar of jkr
>>my pBuff can be more than 32-bit and I only want to get the 4 bytes from where it is pointing to

rstaveley is absolutely on point. His solution will perform exactly what you want. Just my 2 Cents.... :o)
I just don't feel safe to use this casting operation. Is there any other way to do it such as shifting the bits? Thanks
It is the easiest way apart from

int i;

memcpy(&p,pBuff,sizeof(int));

which will do the same - in fact, that's similar to what the compiler will generate when you use the cast.
Oosp, that should have been

int i;

memcpy(&i,pBuff,sizeof(int));
#include <stdio.h>

union U
{
      int val;
      char buf[sizeof(int)];//of buf[4]
};

int main(void) {
      
      char *pBuf="0123456789";
      
      U u;
      for(int i = 0; i < sizeof(int); ++i)
            u.buf[i] = pBuf[i];
      
      printf("%x\n", u.val);
      return 0;
      
}

_novi_
>>     for(int i = 0; i < sizeof(int); ++i)
>>         u.buf[i] = pBuf[i];

You aren't *really* serious to suggest that loop over 'memcpy()' or the cast, are you?
If you're sure that sizeof(int) on your system or platform is really 4 bytes and not more, then i recommend rstaveley's answer, if not, then you might want jkr's. if you really want 4 bytes no matter what, then you might consider using long instead of int because long is guaranteed to be 4 bytes in size.

Anyway, i think your question is sufficiently answered, and, if i may add, with standard, easy and, contrary to your fears, safe approaches. I can't understand why you would want something that is obscure like bit shifting.

;)
> I just don't feel safe to use this casting operation.

Is that because you've yet to get your head round it or that you understand it, but feel that it is not doing what you want?

> pBuff can be more than 32-bit

I assume you mean that pBuff points to an array of more than four unsigned chars. That's not a problem. Provided the first 32 bits (i.e. 4 bytes) contain your integer, your system has a 32 bit word size (i.e. sizeof(int) == 4) and your integer has its bits in the correct order for your system (e.g. is little endian on Intel), the cast will work. reinterpret_cast<int*> says that the compiler should treat pBuff as a pointer to int. By dereferencing the reinterpreted pointer you are asking the value of the pointed-to integer to be taken.
>>>> I just don't feel safe to use this casting operation.

Why cast at all?

   int temp = pBuff[0];

There isn't any advantage or disadvantage of casting.

Regards, Alex



Still uses casts but may be tidier:

char fourBytes[sizeof(int)] = {0x11,0x22,0x33,0x44};
int integer = *((int*)fourBytes);

Paul

   unsigned arr[] = { 3123456789, 3123456789, };
   int  x  = arr[0];
   int  y  = *arr;
   int  z  = *(reinterpret_cast<int*> (arr));

After that, x, y, and z have the same value. That means, all is equivalent.

You don't need a cast to get what you want.

Regards, Alex
> Is that because you've yet to get your head round it or that you understand it, but feel that it is not doing what you want?

According to what I read from the MSDN lib:
"reinterpret_cast Operator
The reinterpret_cast operator allows any pointer to be converted into any other pointer type. It also allows any integral type to be converted into any pointer type and vice versa. Misuse of the reinterpret_cast operator can easily be unsafe. Unless the desired conversion is inherently low-level, you should use one of the other cast operators.
                                                                               
Syntax
                                                                               
reinterpret_cast < type-id > ( expression )
                                                                               
The reinterpret_cast operator can be used for conversions such as char* to int*, or One_class* to Unrelated_class*, which are inherently unsafe.
                                                                               
The result of a reinterpret_cast cannot safely be used for anything other than being cast back to its original type. Other uses are, at best, nonportable.
                                                                               
The reinterpret_cast operator cannot cast away the const, volatile, or __unaligned attributes. See const_cast Operator for information on removing these attributes.
                                                                               
The reinterpret_cast operator converts a null pointer value to the null pointer value of the destination type."


> memcpy(&i,pBuff,sizeof(int));

I have been playing with the memcpy, but do I need to do the ntohl after all?
>>>> I have been playing with the memcpy, but do I need to do the ntohl after all?

Nope, the byte order isn't different between unsigned int and int.

The only difference is the interpretation of the most highest bit that is used as sign bit for integers.

>>>> I have been playing with the memcpy

Again, you *don't* need memcpy or casting to assign between int and unsigned int. A simple

    int i = *pBuff;

is all you need (I wonder if you'll trust me this time ...)

Regards, Alex

Hey BooBoo,

msdn may be right to call reinterpret_cast unsafe but, what you obviously failed to read between the lines is that casting from any pointer type to another pointer type is generally considered unsafe. This is one of the reasons why most other languages did away with pointers and casting a long time ago. Because you are trying to convert the dereferenced value of type char* to type int, you are already 'implicitly' performing a CASTING operation, no matter what method you opt to use. Now using reinterpret_cast does not guarantee safety of an already unsafe practice but at least, it tells the compiler in a no-nonsense way what you intend to do and warns other programmers reading your code that they are stepping into danger zone.

ALex, you can't do this:

int i = *pBuff

because BooBoo's pBuff is of type unsigned char *pBuff, unless you want the c++ compiler to spit on you. ;')

---doc

P.S. Aren't we all glad that we can do all kinds of wonderful stuff (including pointer acrobatics) they can't do on the 'other languages'? Responsibilty is something to be always remembered.
Ooops Alex, sorry. What I meant you can't do is your earlier post:

int i = *pBuff[0];

which is illegal. Now for

int i = *pBuff;

you will only be getting the first byte pointed to by pBuff and not the 4 bytes that BooBoo originally wanted. ;)
> Unless the desired conversion is inherently low-level

The desired conversion that *is* inherently low-level. You have an array of unsigned chars. You are telling the compiler that you know best and that the first four bytes of that array are the bit pattern for an integer of appropriate endianism and correct number of bits.

Using reinterpret_cast<> is the best means at your disposal to say that you know better than the compiler. You can also use a C-style cast, but it is less obvious to a subsequent code reviewer what you are doing.

Consider....

      // This should look alarming, you are reinterpretting the meaning of the bits.
      // For your requirement is correct. You are saying that you do indeed
      // know that the bit pattern should be reinterpretated as a different type.
      int i = *reinterpret_cast<int*>(pBuff);

      // This is less obviously a bit reinterpretation though that's what happens.
      // A quick look at the syntax doesn't immediately tell you that
      // it is a reinterpret_cast<> rather than a static_cast<> or const_cast<>.
      // It is the C programmer's approach, because C programmers
      // are linguistically impoverished ;-)
      // The gerenated code (or lack of it!) is the same as the reinterpret_cast<>
      // but this is not the approach you should adopt for C++.
      int i = *(int*)pBuff;

> Other uses are, at best, nonportable

That's correct. Another system might have 16 or 64 bit integers. The data read into the array might have come from a big-endian system and you are reading it into a little endian system. reinterpret_cast<> says you know that the bit pattern is right for the system for which you are compiling code. Same story for your memcpy() implementation. Passing binary data between systems is much trickier than ASCII text, which is why you get so many text-based protocols on the Internet.