使用void*时如何从数字字面量获取内存地址(指针)?
背景
我在程序中使用通用void*指针,因为它统一、高效,能根据上下文转换为任意类型。调用比较函数时,所有参数必须以void*传递,示例代码:
compare_integer_equal((void*) &r, p12, (void*) NUMBER_1_INTEGER_STATE_CYBOI_MODEL);
其中整数常量的全局定义为:
static int NUMBER_1_INTEGER_STATE_CYBOI_MODEL_ARRAY[] = { 1 }; static int* NUMBER_1_INTEGER_STATE_CYBOI_MODEL = NUMBER_1_INTEGER_STATE_CYBOI_MODEL_ARRAY;
问题
这类常用数字的全局常量总文件大小已超2MB,想要消除这部分占用。虽然可以用局部变量:
int i = 1; compare_integer_equal((void*) &r, p12, (void*) &i);
但数百次比较时,不想承担局部变量的额外内存和时间开销。尝试直接取字面量的地址会触发编译器错误:lvalue required as unary ‘&’ operand,示例:
compare_integer_equal((void*) &r, p12, (void*) &1);
请问:
- 是否有方法从字面量获取内存地址(指针)?
- 还有其他将字面量作为
void*处理的思路吗?
1. 使用静态局部常量(单实例复用)
在调用比较函数的函数内部,定义static const修饰的局部常量。编译器会保证它仅在第一次调用时初始化,后续复用同一个内存地址,既避免全局变量的空间浪费,也不会产生重复创建变量的开销:
// 函数内部定义,仅初始化一次 static const int num_1 = 1; compare_integer_equal((void*) &r, p12, (void*) &num_1);
这种方式下,每个字面量只会生成一个内存实例,且仅在当前函数范围内可见,不会污染全局命名空间,可执行文件体积远小于全局数组+指针的实现。
2. 利用C99复合字面量
C99标准支持的复合字面量可以直接创建匿名常量实例,无需显式定义变量就能取其地址作为void*传递:
compare_integer_equal((void*) &r, p12, (void*) &(const int){1});
复合字面量的生命周期:函数内使用时与自动变量一致,全局作用域使用时与全局变量一致。对于频繁调用的场景,编译器通常会自动优化,避免重复实例化的开销。
3. 封装比较函数,支持直接传字面量
如果允许修改接口或新增封装,可以用宏实现兼容,让调用方直接传字面量,内部完成指针转换:
// 保留原函数兼容旧代码 int compare_integer_equal(void* a, void* b, void* c); // 封装宏,自动创建临时常量 #define COMPARE_INTEGER_EQUAL(a, b, val) \ do { \ const int tmp = (val); \ compare_integer_equal((a), (b), (void*)&tmp); \ } while(0) // 调用方式更简洁 COMPARE_INTEGER_EQUAL((void*)&r, p12, 1);
编译器会对临时变量做优化,实际运行开销几乎可忽略,同时提升代码可读性。
4. 直接转换字面量为void*(仅限特定场景)
如果compare_integer_equal内部实际是将void*转换为整数类型比较(而非解引用指针访问内存),可以直接把字面量强制转换为void*:
compare_integer_equal((void*) &r, p12, (void*) (intptr_t)1);
警告:这种方式仅适用于函数逻辑处理指针数值的场景,若函数需要解引用指针,会触发未定义行为,必须确认函数实现后再使用。
内容的提问来源于stack exchange,提问作者Christian Heller

