【发布时间】:2020-04-06 06:02:05
【问题描述】:
如果我正在使用当前使用特定数字类型别名的库,例如
typedef uint32_t library_type;
void library_function(library_type x);
我如何确保需要从不同类型传入值的代码保持正确,即使库更改了其 typedef?
uint64_t x = get_some_number();
// …need checks here…
library_function((library_type)x);
我可以添加以下检查:
assert(sizeof library_type >= sizeof uint32_t);
assert(x <= UINT32_MAX);
第二次检查将确保我得到的值在 current library_type 的范围内。库作者没有提供LIBRARY_TYPE_MAX 定义,因此第一个检查试图保护第二个,以防library_type 在将来编译代码时出于任何原因而更改。
如果 library_type 更改为例如int8_t,但如果 library_type 改为 int32_t 会怎样?它仍然是正确的“大小”,但范围仍然小于我正在检查的范围!
C 语言是否提供了一个内省类型符号的运算符,就像sizeof 让我知道宽度一样?有没有其他方法可以确保只有在正确的情况下才能到达我对library_type 的演员表?
【问题讨论】:
-
您混淆了运行时和编译时检查。 C 在运行时并没有真正执行动态类型(除非您构建自己的某种方案来存储应该用于重新解释 C 最初将其视为原始数据的类型),因此您进行任何检查以确定是否源代码已更改必须在编译时进行,而不是像 assert() 这样的运行时检查。
-
看起来 C++11 提供了
std::is_signed;在这里我想知道C中是否有类似的东西(以及这是否是正确的方法;-) -
您是否试图防止对库源代码的错误编辑,或在运行时传递给库的错误参数?这两个问题都不是特别可以解决的,但在你澄清你的确切恐惧之前,这个问题真的是无法回答的。
-
你不能删除显式转换然后用
-Wconversion捕获不正确的隐式转换吗?得到类似的东西:conversion to uint32_t {aka unsigned int} from int32_t {aka int} may change the sign of the result -
那么在调用函数之前将其转换为您想要检查的类型。
uint32_t x_cast = (uint32_t) x; library_function(x_cast);
标签: c casting typedef unsigned signed