?
Solved

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

Posted on 2005-03-02
23
Medium Priority
?
540 Views
Last Modified: 2008-01-09
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
0
Comment
Question by:BooBoo1025
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
  • 3
  • +5
23 Comments
 
LVL 17

Accepted Solution

by:
rstaveley earned 1500 total points
ID: 13445460
If you have 32-bit integers and pBuf points to a 32-bit integer with the appropriate endianism, you can simply write:

      int i = *reinterpret_cast<int*>(pBuff);
0
 

Author Comment

by:BooBoo1025
ID: 13445490
well, my pBuff can be more than 32-bit and I only want to get the 4 bytes from where it is pointing to.
0
 
LVL 3

Expert Comment

by:Dawaffleman
ID: 13445764
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
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:BooBoo1025
ID: 13445805
Dawaffleman,
     If I do that, then I will get the fourth element from the pBuff, which is not what I want.
0
 
LVL 3

Expert Comment

by:Dawaffleman
ID: 13445821
well if each element was one byte which a character is (correct?) then it should get the fourth byte, or charater
0
 

Author Comment

by:BooBoo1025
ID: 13445859
but the fourth byte is different than 4 bytes. I want to be able to get all 4 bytes.
0
 
LVL 3

Expert Comment

by:Dawaffleman
ID: 13445906
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.




0
 
LVL 86

Expert Comment

by:jkr
ID: 13446137
>>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)
0
 

Author Comment

by:BooBoo1025
ID: 13446281
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
0
 
LVL 86

Expert Comment

by:jkr
ID: 13446300
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.
0
 
LVL 86

Expert Comment

by:jkr
ID: 13446303
Oosp, that should have been

int i;

memcpy(&i,pBuff,sizeof(int));
0
 
LVL 8

Expert Comment

by:novitiate
ID: 13446326
#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_
0
 
LVL 86

Expert Comment

by:jkr
ID: 13446338
>>     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?
0
 
LVL 4

Expert Comment

by:markdoc
ID: 13446884
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.

;)
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 13447294
> 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.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13449947
>>>> 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



0
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 13450203
Still uses casts but may be tidier:

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

Paul
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13450359

   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
0
 

Author Comment

by:BooBoo1025
ID: 13451527
> 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?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 13452071
>>>> 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

0
 
LVL 4

Expert Comment

by:markdoc
ID: 13455171
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.
0
 
LVL 4

Expert Comment

by:markdoc
ID: 13455205
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. ;)
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 13456821
> 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.
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
Suggested Courses

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question