如何正确地将负数添加到 size_t

How to properly add a negative number to a size_t

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

所以如果我的列表中有 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]

解决向 size_t 这样的无符号值添加负数 int32_t 的正确方法是什么?我认为这是一个简单的答案,比如转换为处理 size_t 和 int32_t 的更大类型(int64_t?ptrdiff_t?)......但是你如何确定哪个是要投射到的正确类型(如果那是正确的解决方案)?

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

无符号数的算术以 M 为模运算,其中 M 比最大可表示值多一(例如 256 表示 8 -bit unsigned char 其最大值为 255)。这包括转化。所以,如果我们有一个无符号的 a 和一个有符号的负数 b,将 b 转换为无符号的 b type yields M + b (注意,因为 b 是负数,所以 M + b 小于 M)。然后添加 a 在数学上是 a + M + b , 模 M, 是 a + b.