如何在size_t中正确添加负数

时间:2019-07-25 18:32:55

标签: c unsigned signed integer-arithmetic

我想在列表实现中支持负索引,我要处理此问题的方式(我知道可能有更好的方法来处理负索引)是通过将负值添加到列表中的元素总数。

因此,如果我的列表中有12个元素,并且我要求索引为-5,则我将执行12 + (-5) = 7,因此我用来检索该元素的实际索引为7。

我认为必须进行一些强制类型转换,并且我可以尝试使用ptrdiff_t之类的一堆类型,但是我想学习如何确定哪种类型是正确的类型。

// the size of the list (normally something like list->num_nodes)
size_t list_size = 12;

// the int32_t is the index argument given to an indexing function
int32_t index = -5;

// the size_t is the real index that can be passed to my internal
// indexing function that will walk from either list head or tail
// depending on whether the index is closer to start or end.
size_t real_index = 0;

// if the index is less than 0 I want to add it to the list size
// to effectively subtract, otherwise just assign it
if (index < 0) {
    real_index = (list_size + index); // << warning here
} else {
    real_index = (size_t)index;
}

但是将int32_t索引添加到size_t list_size会导致gcc警告:

warning: conversion to ‘long unsigned int’ from ‘int32_t {aka int}’ may change the sign of the result [-Wsign-conversion]

什么是解决将负int32_t添加到像size_t这样的无符号值的问题的正确方法?我认为这是一个简单的答案,例如将其转换为可以处理size_t和int32_t(int64_t?ptrdiff_t?)的较大类型。但是,如何确定要转换为哪种正确类型(如果这是正确的解决方案)?

1 个答案:

答案 0 :(得分:4)

您可以将int32_t投射到size_t并将其添加。该算法将正常工作;添加已转换为无符号值的负值的结果将导致无符号值减少原始负值。

具有无符号数字的算术运算以 M 为模,其中 M 比最大可表示值大(例如,对于8位unsigned char为256)最大值是255)。这包括转化。因此,如果我们有一个无符号的 a 和一个有符号的负 b ,则将 b 转换为无符号类型会生成 M + b (请注意,由于 b 为负,因此 M + b 小于 M )。然后添加 a 在数学上是 a + M + b ,对 M 取模,是 a + b