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

Reply via email to