在项目中,用匿名结构体的地址作为常量来标识不同业务类型(例如 A 、B 、C 、D……),
这样做的目的是彻底避免魔术数字( magic number ),并且希望在逻辑判断中直接通过指针比较。
代码 h 文件
typedef struct __BizType *BizTypeRef;
// 对外暴露的常量声明
extern const BizTypeRef kBizTypeA;
extern const BizTypeRef kBizTypeB;
extern const BizTypeRef kBizTypeC;
extern const BizTypeRef kBizTypeD;
实现文件
// 定义结构体
struct __BizType {
int value;
};
// 定义常量指针
const BizTypeRef kBizTypeA = &(const struct __BizType){ .value = 1 };
const BizTypeRef kBizTypeB = &(const struct __BizType){ .value = 2 };
const BizTypeRef kBizTypeC = &(const struct __BizType){ .value = 3 };
const BizTypeRef kBizTypeD = &(const struct __BizType){ .value = 4 };
使用
// 使用示例
void handleBiz(BizTypeRef type) {
if (type == kBizTypeA) {
// 处理业务 A
} else if (type == kBizTypeB) {
// 处理业务 B
}
}
![]() |
1
r6cb 8 天前
为什么不用枚举?
|
2
liuidetmks OP @r6cb 枚举还是数字啊,还是能使用 1 当做参数传入。 我想完全只使用定义的这几个变量,政出一门
|
3
aprikyblue 8 天前 ![]() 你看看 enum class
|
4
cwxiaos 8 天前 via iPhone
或许可以叫做更安全的枚举,限制下游代码乱搞
|
![]() |
5
minamo 8 天前 via Android
如果你真这么讨厌魔数,倒也不是不行,但我觉得不值得
|
6
iOCZS 8 天前
本该在语法层解决的问题,在用户侧试图解决,会引入复杂性
|
![]() |
7
ysc3839 7 天前 via Android ![]() 这么写的话进行比较时可能并不是直接比较常量,而是要从全局变量里读取值,降低性能。
而且实现文件里这么取临时对象的地址,不怕编译器把这四个对象都优化成使用同一空间?不怕去到悬垂指针出现什么 UB ? 需要枚举类型的地方,能直接传递整数,是 C 允许隐式转换的问题,建议想办法调整编译参数,禁止这种行为,或者迁移到更严格的 C++。 |
![]() |
8
xuanbg 7 天前
魔数有什么问题吗?其实魔数一点问题都没有,你先定义一个常量,无非就是脱裤子放屁——多此一举
|
9
metalvest 7 天前
为什么不直接用 std::type_index
|
10
liuidetmks OP @metalvest c
@ysc3839 全局作用域不会 ub 吧 比较的话是比较两个指针地址,性能不存在问题的 @xuanbg 有时候业务变化了,魔数可能哪里弄漏了,这里把结构体匿名,提供一个统一构造方法,方便处理一点。 @aprikyblue c |
11
kneep 7 天前 ![]() @liuidetmks @ysc3839 可能是在说全局指针地址的读取可能会多产生一条指令,而常量通常不需要。应该不是在说你比较了指针指向的内容。
|
![]() |
12
ysc3839 7 天前 via Android
@liuidetmks 地址数值是存在全局变量里的,要先读全局变量,再比较数值
|
![]() |
13
geelaw 7 天前 ![]() @aprikyblue #3 楼主写的是 C 不是 C++,没有 enum class 。(当然,换成 C++ 似乎是比较好的选择。)这一点可以从这段代码可以编译知道(见下面第二点)。
———— 几个可以挑剔的点: 一双下划线是保留标识符。 二是初始化的时候 constness 不合适,注意 const BizTypeRef 是 struct __BizType * const 而不是 struct __BizType const *,于是这里会丢失 const ,如果实现方(很容易无意间)尝试修改只读复合字面量的 .value 的话会有 UB 。 三是,如果实现方不需要数据,那么实际上没有必要使用 value ,用 non-const 复合字面量本身就可以确保几个表达式的对象不占据相同的位置(但是 const 复合字面量可能会是同一个对象)。 ———— @ysc3839 #7 楼主的版本有不同的值,所以无法是同一个位置。在文件作用域的复合字面量是静态存储期。 |
14
cybort 7 天前 via Android
代码静态扫描能解决的问题,为什么要通过编码解决?
|
![]() |
15
chenxytw 7 天前
Your solution is not better than use `0xdeadbeef01`, `0xdeadbeef02` or other long and unique value to define the enum. The long and unique value is friendly to search and replace.
|
![]() |
16
coyove 7 天前
楼上已经说了,用魔数 greppability 更好,在超大型项目中更有用
|