static int* (*const p[])();
p是一个函数指针静态常量数组,即p是静态成员变量,p的成员是函数指针且不能修改p的数组成员指向。p的成员函数指针指向的是空入参、返回值是int指针的函数。
i += !!i
若i为0,则!i为1;若i为非0,则!i为1。所以,若i为0,!!i为0;若i为非0,则!!i为1。
所以,此表达式的含义是当i为0或无效(NULL)时,i不变;若i当前值有效(非0)时,则加1(指向下一个)。
枚举位运算
首先复习一下位运算符:
运算符 | 含义 | 示例 | 说明 |
---|---|---|---|
& | 位AND | x&y | 当且仅当x=y=1时,结果为1,否则为0 |
| | 位OR | x|y | 当且仅当x=y=0时,结果为0,否则为1 |
^ | 位XOR | x^y | 当x=y时,结果为0;当x≠y时,结果为1 |
~ | 位NOT | ~x | 当x=1时,结果为0;当x=0时,结果为1 |
<< | 向左位移 | x<<y | x的每位向左移动y位 |
>> | 向右位移 | x>>y | x的每位向右移动y位 |
对于表达式x<<y,其中若x=1,则表达式为1<<i。该表达式表示
2
i
2^{i}
2i:
1<<0
⟹
\Longrightarrow
⟹ 0001
⟶
\longrightarrow
⟶ 0001
1<<1
⟹
\Longrightarrow
⟹ 0001
⟶
\longrightarrow
⟶ 0010
1<<2
⟹
\Longrightarrow
⟹ 0001
⟶
\longrightarrow
⟶ 0100
1<<3
⟹
\Longrightarrow
⟹ 0001
⟶
\longrightarrow
⟶ 1000
下面说明两个常见的枚举位表示及运算:
enum Enum1 : unsigned
{
First = 1 << 0, //0001
Second = 1 << 1, //0010
Third = 1 << 2, //0100
Fourth = 1 << 3, //1000
}
//unsigned也可以是Enum1类型。下面为位或运算,如果将Enum1枚举的每项看作标识符,则i可以同时表示First和Third。
unsigned i = (First | Third); // 0001 | 0100 = 0101
//移除标识。下例表达式将会把Third从i中移除。
unsigned newi = i & ~Third; //i & ~Third
i = newi;
//判断i是否标识某个标识符
//i & First => true, 0101 & 0001 = 0001
//i & Third => true, 0101 & 0100 = 0100
if(i & First) {}
//判断i中是否包含任意或所有某个标识符集合。
Enum1 i = (First | Third | Fourth);
Enum i1 = (First | Second);
Enum i2 = (First | Third);
Enum i3 = (First | Second);
//判断i中是否包含i1中的某项。i1中的Second项虽然不在i中,但是i却包含First项,所以此处为true。
if((i & i1) != 0) {}
//判断i中是否包含i2的所有项。因为i中既包含First和Third,所以为true。
if((i & i2) == i2) {}
//因为i中不包含i3中的Second项,所以为false。
if((i & i3) == i3){}
直接使用十六进制表示枚举值:
enum Enum2
{
None = 0x00000000u,
First = 0x00000001u,
Second = 0x00000002u,
Third = 0x00000004u,
Fourth = 0x00000008u,
Fifth = 0x00000010u,
Sixth = 0x00000020u,
Seventh = 0x00000040u,
Eighth = 0x00000080u,
Ninth = 0x00000100u,
...
}
//枚举值使用十六进制显式表示
结构体指针转换
不同类型的结构体指针可以进行任意转换,因为指针只是指向内存中的某一地址。对于结构体指针,它就是指向结构体在内存中的起始地址。所以,可以不同结构体指针间可以进行转换。下面给一个应用中的例子:
enum EStructType
{
Int,
Double,
Object
}
struct FTypeBase
{
EStructType Type;
}
struct FInt
{
EStructType Type;
int Index;
}
struct FDouble
{
EStructType Type;
double Number;
}
struct FObject
{
EStructType Type,
Object* Obj;
}
static FInt NewInt = {Int, 88};
static FDouble NewDouble = {Double, 0.88};
static FObject NewObject = {Object, new Object()};
//把不同类型的结构体对象获取它们的结构体指针保存到数组,这样就可以统一保存和调用。
static FTypeBase* TypeBaseArray[] =
{
(FTypeBase*)&NewInt, //NewInt结构体指针保存到数组
(FTypeBase*)&NewDouble,
(FTypeBase*)&NewObject
};
//根据Type判断结构体类型,然后转换会对应的结构体指针
if(TypeBaseArray[0]->Type == Int)
{
FInt* CastInt = (FInt*)TypeBaseArray[0];
int Index = CastInt->Index;
}