cJSON中#define cJSON_IsReference 256 和 #define cJSON_StringIsConst 512这定义的大小是?
在 cJSON 中,#define cJSON_IsReference 256
和 #define cJSON_StringIsConst 512
是位掩码(bitmask),它们的值(256
和 512
)是精心选择的,目的是在 cJSON
结构体的 type
字段中进行按位操作,以标记不同的对象属性。
1. 为什么是 256 和 512?
这两个值是 2 的幂,对应二进制表示中的单个位:
-
256
=0x100
=0000 0001 0000 0000
(第 9 位为 1,其余为 0) -
512
=0x200
=0000 0010 0000 0000
(第 10 位为 1,其余为 0)
这样设计是为了:
-
避免冲突:
type
字段的低 8 位(0-7)用于存储 JSON 数据类型(如cJSON_Number
、cJSON_String
等),而高位(8-15)用于存储额外标志。 -
支持位运算:可以通过
|
(或)设置标志,&
(与)检查标志,~
(非)清除标志。
2. type
字段的结构
cJSON
结构体的 type
字段是一个 int
,其布局如下:
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Reserved | StringIsConst | IsReference | JSON 数据类型(如 String、Number) |
-
低 8 位(0-7):存储 JSON 数据类型(如
cJSON_String = 4
,cJSON_Number = 8
)。 -
高位(8-15):存储额外标志,如
IsReference
(第 9 位)和StringIsConst
(第 10 位)。
3. 如何设置和检查这些标志?
cJSON 提供了宏来操作这些标志:
// 设置标志
#define cJSON_SetFlag(object, flag) ((object)->type |= (flag))
#define cJSON_UnsetFlag(object, flag) ((object)->type &= ~(flag))// 检查标志
#define cJSON_IsReference(object) ((object) && ((object)->type & cJSON_IsReference))
#define cJSON_StringIsConst(object) ((object) && ((object)->type & cJSON_StringIsConst))
示例:
cJSON *obj = cJSON_CreateString("Hello");
cJSON_SetFlag(obj, cJSON_StringIsConst); // 标记为常量字符串if (cJSON_StringIsConst(obj)) {printf("该字符串是常量,不会被 cJSON_Delete 释放\n");
}
4. 为什么不用 enum
或 bool
?
-
性能优化:位运算比
bool
或enum
更高效,尤其是在频繁操作 JSON 树时。 -
内存节省:
type
字段只需要 16 位(int
),而如果用多个bool
变量会占用更多内存。 -
兼容性:cJSON 设计为轻量级,适用于嵌入式系统,位操作是最优选择。
5. 总结
宏 | 十进制值 | 十六进制 | 二进制(位位置) | 用途 |
---|---|---|---|---|
cJSON_IsReference | 256 | 0x100 | 0000 0001 0000 0000 (第 9 位) | 标记对象是引用(共享数据) |
cJSON_StringIsConst | 512 | 0x200 | 0000 0010 0000 0000 (第 10 位) | 标记字符串是常量(不应释放) |
这两个宏的值(256 和 512)是按位设计的,确保它们不会与 JSON 数据类型(低 8 位)冲突,并能高效地进行标志管理。