【问题标题】:Casting typedef'd numeric type to size_t catching overflows将 typedef 的数字类型转换为 size_t 捕获溢出
【发布时间】:2016-07-05 16:29:55
【问题描述】:

我有一个未知的 typedef 数字类型。如果可能的话,我想将其转换为 size_t(阅读:如果它在 size_t 的范围内),否则会遇到一些错误处理代码。

有便携的方法吗?

实际上我想做的是:

some_int_type val = <blah>;
if (val < 0 || val > SIZE_MAX) {
    // handle error
} else {
    return (size_t) val;
}

但是,这不起作用,因为 val 可能已签名。

我的第二个想法是这样做:

if (val < 0 || (unsigned_some_int_type) val > SIZE_MAX) {
    // handle error
} else {
    return (size_t) val;
}

这可行(我认为)——除了我没有some_int_type 的未签名版本。我可以将它们都转换为some_int_type,但如果some_int_type 小于size_t,那将无法正常工作(如果some_int_type 已签名,则也无法正常工作,现在我考虑了一下) .我可以将它们都转换为uintmax_t - 除了一些编译器实际上具有大于uintmax_t 的整数类型。 (值得注意的是,__[u]int128)。

那我该怎么做呢?

【问题讨论】:

  • 为什么第一版不行?
  • 一个类型怎么可能是“未知的”?
  • @EugeneSh。当它位于编译时构建的外部库中时。
  • 我自己对此并不熟悉,但这对我来说似乎是 的情况。
  • @TLW 如果编译器知道 - 它是已知的。

标签: c casting


【解决方案1】:

OP的原代码应该没问题

some_int_type val = <blah>;
if (val < 0 || val > SIZE_MAX) {
    // handle error
} else {
    return (size_t) val;
}

OP commented to @Olaf“错误:有符号和无符号整数表达式之间的比较”。 OP 确实看到了 警告 或警告被视为错误。 IAC,这不是每个 C 的错误。

如果 OP 无法忽略警告/错误,则轻轻仅根据需要转换为 size_t。如果未知类型比size_t 宽,则将其乘以(size_t)1 不会改变类型并且不应该出现比较警告。 IAC,val的值不会改变。

#include <stdint.h>
if (val < 0 || (size_t)1 * val > SIZE_MAX) {

让编译器优化它。只有较小的编译器可以使用(size_t)0 + val


进一步:消息“有符号和无符号整数表达式之间的比较”仅在 select 有符号整数和无符号整数比较中出现。当无符号整数适合有符号整数类型的范围时,它不会出现,因为将无符号整数类型转换为更宽的有符号整数类型没有问题。

【讨论】:

  • 这是一种很好的演员阵容。是的,Werror 已启用。
【解决方案2】:

担心缺少未签名的版本,将其拉入测试中是否为阳性

if (val >= 0 )
{
    if (val <=  SIZE_MAX)
    {
        return (size_t) val;
    }
}

// Handle error
return 0;

【讨论】:

  • 这在语义上与 OP 的第一个代码没有区别。 OP 很好,因此也很好,但没有理由比 OP 更喜欢这个。
  • 纯粹是推测性的,但如果代码位于断言值为正的块内,则深度 linter(如覆盖率)可能不会警告缺少签名
  • 如果valunsigned 类型,第一行将生成警告,因为在这种情况下条件始终为真。
  • 我不知道为什么coverity 会关心类似于条件编译技术的东西(条件始终为真)。对于编译器的优化器来说,这似乎更多的是工作。但如果你的测试表明,好的
【解决方案3】:

检查否定情况后,检查相关类型的大小是否大于size_t。如果是这样,请将SIZE_MAX 转换为some_int_type 并进行比较。如果不是,则该值不能大于SIZE_MAX

if (val < 0) {
    // handle error
} else if ((sizeof(some_int_type) > sizeof(size_t)) && (val > (some_int_type)SIZE_MAX)) {
    // handle error
} else {
    return (size_t) val;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-29
    • 2013-05-27
    • 2019-01-05
    • 1970-01-01
    相关资源
    最近更新 更多