应该将整数类型显式转换(例如,将“ int”转换为“ unsigned”)还是只会增加混乱?

时间:2018-09-24 00:12:48

标签: c++ c

这是一个很小的问题,因此我很抱歉,如果它太宽泛或可能重复。我搜索并发现了几个有关隐式整数转换如何工作的问题,但没有一个问题在问这是否是好事。我通常不会关心这个问题,但是编译器对隐式转换给出的所有响亮而恼人的警告使我怀疑这是否被视为问题。

作为一个简单的示例,下面是一个片段,该片段调用一个函数,该函数需要一个链表,一个整数(索引)和一个无符号整数(范围),该整数将从链表中删除指定的范围。

const int64_t first = foo;
const int64_t last  = bar;
const int     diff  = last - first; /* int for example's sake */
/* ... */
ll_delete_range_at(baz->ll, first+1, diff-1);

死的简单;不太有趣。但是clang抱怨传递给函数的值会缩短,在第二种情况下,符号会更改。假设我知道(如我在这里所做的那样)不会有溢出问题,并且值始终为正,这实际上是一个问题吗?一个人应该这样显式地投射吗?

ll_delete_range_at(baz->ll, (int)(first+1), (unsigned)(diff-1));

据我所知,这只会增加混乱,并明确声明程序员知道已完成强制转换并确信它们可以。那值得搞乱吗?

2 个答案:

答案 0 :(得分:7)

频繁转换造成的杂乱无章是体系结构不良的征兆,而不是显式强制转换错误的征兆。

  1. 如果您知道特定的变量或成员将始终处于特定的范围或大小,请从头开始使用适当的类型声明它们。

  2. 如果需要使用的类型必须用特定的范围或大小进行声明,则这是有原因的,并且该原因将在您使用它们的任何地方有效,因此在整个代码中都应坚持使用这些类型

  3. 如果在特殊情况下必须强制转换(例如,当合并两个使用不同类型的库时),然后使用适当的错误处理将转换强制封装在辅助函数或包装器类中。

答案 1 :(得分:2)

应该建议将

C样式强制转换为int和snd unsigned,因为根据我的经验,不小心将指针提供给他们,并且它成为重新解释的强制转换。使用static_cast

第二,这些强制转换是等待发生错误的标志;如果int不适合int64_t,我们只会得到未指定的溢出。而2^31上方的较大的无符号值可能不是我们要在diff==0时删除的元素数量。

因此,从某种意义上讲,它们是代码中存在危险问题的绝佳文档。

当前程序员“知道”这些值是安全的。从现在开始的7年,数月或数天的不同程序员“知道”任何有效的64位值都可用于firstlast,并且diff中的0是合理的,以后的代码不应令人窒息。

描述diff不能为0且两个64位值之间必须在2 ^ 31-1之内的代码约定,这使代码在此处更加明显。

所有这些都源于一对无害可怕的C样式强制转换和一些在数字上值得怀疑的函数调用。

显式强制转换比隐式转换更好,但是类型转换本身在这里很麻烦。通常,类型更改是即将出现的错误和围栏错误的标志。进行防御性编程并处理边界检查,除非您知道代码处在关键的性能路径上;否则,请重新进行操作。然后,在关键的性能路径中确定类型。