On Wed, Jan 22, 2014 at 5:23 AM, S. Dale Morrey <sdalemor...@gmail.com> wrote:
> For instance in many places, Origin has... > pstart->nVersion > > but fork1 has > pstart->nVersion&0xff > > According to the header nVersion is defined as an int. > > For the life of me I just can't understand what fork1 is doing with that > line of code. It's possible that this code was present in the origin code > base and only modified later, frankly I'm not sure how I would go about > checking. > > Still the line is bothering me, it's used in several places usually in > something along the lines of > if(pstart->nVersion >= 2){do something} > > and in the fork code it's the same except fork1 has the &0xff part as well. > if ((pstart->nVersion&0xff) >= 2){do something} > > I'm reading the origin code as > pstart object nVersion > > and the fork1 code as > pstart object nVersion at byte 255 > > So it's not making much sense to me. > I realize that an int in C++ is 4 bytes, and so this may be saying look at > only the first (or possibly second) 2 bytes. Even so I'm not sure which it > may be saying to look at or for that matter why would we only look at 2 > bytes of a 4 byte int. The type 'int' in C++ varies in representation depending on the architecture. Specifically, it's: * not smaller than 'short' * at least 16 bits (on a 32/64-bit system, it will usually be at least 32 bits, but there is no guarantee of this in the spec) * signed See the std::numeric_limits template class in <limits> to determine the numeric properties of the base types in the standard C++ way. To find out what they are in C, you'd use <stdint.h> In either language, the 'sizeof' operator will give you the size of any variable or type (types must be parenthesized, but variable names need not be). Note that 'sizeof' returns the size in multiples of the 'char' type's size, i.e. 'sizeof (char)' is always 1. The type 'char' in C++ is defined to be: * large enough to store any member of the implementation's basic character set (which is not defined by the spec) * possibly holds negative values (implementation-defined) * all bits participate in the representation (no padding) * for unsigned char, all bit patterns represent numbers Note that nothing there says '8 bits'; there are some platforms where the bit-width of char is not 8. A co-worker of mine was fairly recently programming a DSP chip where the bit width of char was 32 bits, which was the addressable unit of the processor. Of course, this meant that sizeof (int) = 1 for that platform. He was very confused for a while. Also note that if the C or C++ specifications speak of a 'byte', they really mean a 'char'. They normally don't use 'byte', though, as it is not an unambiguous term. So... on to the code. pstart->nVersion&0xff There are two operators in this expression, '->' and '&'. They are both left-associative, and '->' has higher precedence. So this is equivalent to: (pstart->nVersion) & 0xff The '->' operator is the "member of pointer" operator. Unless it's overloaded, in which case it might do something unexpected, it dereferences the pointer to its left and looks up the member named on its right at the dereferenced struct/object. Unless that member is a function or enumeration, the result will be an lvalue designating that member. You didn't explicitly give the type of the nVersion member; based on what you *did* say I will assume it is 'int', but if it's actually something different then the following could be not quite correct. So, we have an lvalue of type int on the left of the '&' operator and a hexadecimal literal value on the right. A literal with no suffix will have the smallest type of int, long int, or long long int that it will fit in. So, at least 16 bits, most likely 32, a signed quantity, and all but the least significant 8 bits are zero. We have an 'int' on the left and an 'int' on the right, so no integral type conversion takes place. The '&' operator is the bitwise-AND operator. Since both sides have the same bit width, the implementation is the obvious bitwise AND (unless it was overloaded, of course), which will have the effect of setting all but the least significant 8 bits of the final value to 0, with the least significant bits retaining the value they had on the left-hand side. So the final evaluation of the expression is an rvalue of type int. It will be a positive integer between 0 and 255 consisting of the least-significant 8 bits of the value stored at pstart->nVersion. This seems like an odd thing to do to a version number, but it might be reasonable if it's going to be put into an 8-bit field somewhere after the quoted bit of code. It would ensure that you didn't try to stuff more than 8 bits into the 8-bit field, but it would certainly mangle version numbers that were negative or too large to fit. --Levi /* PLUG: http://plug.org, #utah on irc.freenode.net Unsubscribe: http://plug.org/mailman/options/plug Don't fear the penguin. */