While reading the source code for RakNet on GitHub, I came across the following in RakNetDefines.h.
typedef unsigned char RPCIndex;
const int MAX_RPC_MAP_SIZE=((RPCIndex)-1)-1;
const int UNDEFINED_RPC_INDEX=((RPCIndex)-1);
When running the following code via an online C++ compiler:
#include <iostream>
typedef unsigned char RPCIndex;
const int MAX_RPC_MAP_SIZE=((RPCIndex)-1)-1;
const int UNDEFINED_RPC_INDEX=((RPCIndex)-1);
int main() {
std::cout << MAX_RPC_MAP_SIZE << " ";
std::cout << UNDEFINED_RPC_INDEX;
return 0;
}
I get 254 255 as the output. While I know that 255 is (typically) the maximum value for an unsigned char in C++, I was shocked to see that simply putting the name of a type and subtracting one from it resulted in it’s maximum value. Furthermore, writing (RPCIndex)-0 evaluates to 0. Why is this the case in C++? Is there a historical reason for it, is it just convenient, or am I missing something?
>Solution :
(RPCIndex)-1 is parsed as a C-style cast expression of the form (T)E where T is a type and E an unary expression.
In this case T is the type RPCIndex and E is the expression -1 which is a unary minus operator applied to the 1 integer literal.
The result is the value -1 converted to RPCIndex. Because RPCIndex is an unsigned integral type, the result is the representable value of RPCIndex congruent to -1 modulo 2**w where w is the width of the RPCIndex integer type. In other words, it produces 2**w-1, the largest representable value of the unsigned integer type.
I guess you can see how (RPCIndex)-0 works…
This -1 cast trick originates from C where there is no other way to name the maximum value of some aliased unsigned integer type without knowing what it aliases or what its maximum value is apriori.
In C++ it can be expressed much more clearly what the intent is with std::numeric_limits from <limits>. The -1 trick is not necessary anymore:
const int UNDEFINED_RPC_INDEX = std::numeric_limits<RPCIndex>::max();
In general the code looks more like C than (modern) C++ code, although it behaves as expected in C++ as well.