C 是否提供运算符来检查类型的签名?

Does C provide an operator to check the signedness of a type?

如果我正在使用当前使用特定数字类型别名的库,例如

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);

第二次检查将确保我得到的值在 currentlibrary_type 的范围内。库作者没有提供 LIBRARY_TYPE_MAX 定义,因此第一个检查试图保护第二个,以防将来编译代码时 library_type 因任何原因发生更改。

如果 library_type 更改为例如int8_t,但是如果 library_type 改为 int32_t 呢?它仍然是正确的 "size" 但范围仍然小于我正在检查的范围!

C 语言是否提供了一个运算符来检查类型的符号,就像 sizeof 让我知道宽度一样?有没有其他方法可以确保我对 library_type 的转换只有在正确的情况下才能实现?

How would I ensure that code which needs to pass in a value from a different type remains correct, even if the library changes its typedef?

您要防御的情况是不负责任的人类行为之一,而不是技术行为。

更改 API 中参数的 typedef 是 "breaking change" - 就像任何其他行为更改一样。这样的更改,如果不仅仅是一个错误修复,也可能是对其他可能更微妙和更严重的更改的暗示。

重大更改应记录在发行说明中。

通常,如果在 API 中自动执行重大更改,则可以通过版本标识符或功能查询等方式在构建 and/or 运行时进行检查 - 在某处库 headers 将是 #define LIBRARY_WHATEVER_VERSION 3 然后你的代码可以有预处理器指令来检查它。

当重大变更非常严重时,通常会重命名软件本身,以至于错误的版本甚至无法满足#include 或 link 次尝试。

是的,关系运算符与强制转换运算符相结合。例如:

_Bool TYPE_is_signed = ((TYPE)-1 < 0);

或者作为断言:

assert((TYPE)-1 < 0); // Require that TYPE is signed
assert((TYPE)-1 > 0); // Require that TYPE is unsigned