在数组迭代器中使用size_t

J C*_*ins 12 c c++ arrays size-t

我最近了解到,引入size_t是为了帮助面向未来的代码,防止本机位数增加和可用内存增加.具体的使用定义似乎是存储某些东西的大小,通常是一个数组.

我现在必须想知道这种未来的证明应该走多远.当迭代数组的下一个任务使用一个unsigned intas作为索引数组时,使用面向未来并且大小适当的size_t定义数组长度毫无意义:

void (double* vector, size_t vectorLength) {
    for (unsigned int i = 0; i < vectorLength; i++) {
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

事实上,在这种情况下,我可能希望语法严格地将unsigned int上变换为关系运算符的size_t.

这是否意味着迭代器变量i应该只是一个size_t

这是否意味着任何程序中的任何整数必须在功能上确定是否它将被用作数组索引?

它意味着使用编程开发索引然后应该创建size_t类型的一个新的结果值,特别是如果逻辑依赖于潜在符号的整数值逻辑的任何代码?即

double foo[100];
//...
int a = 4;
int b = -10;
int c = 50;

int index = a + b + c;
double d = foo[(size_t)index];
Run Code Online (Sandbox Code Playgroud)

当然,由于我的代码逻辑创建了一个固定的边界,因此向上转换为size_t不会提供额外的保护.

Sha*_*baz 14

您应该记住该语言的自动转换规则.

这是否意味着迭代器变量我应该只是一个size_t?

是的,因为如果size_t大于unsigned int且你的数组实际上大于可以用a索引unsigned int,那么你的变量(i)永远不会达到数组的大小.

这是否意味着任何程序中的任何整数必须在功能上确定是否它将被用作数组索引?

你试图让它听起来很激烈,而事实并非如此.为什么选择变量double而不是float?你为什么要做一个变量unsigned而不是?你为什么要做short另一个变量int呢?当然,你总是知道你的变量将用于什么,所以你决定他们应该得到什么类型.选择size_t是众多之一,同样也是如此.

换句话说,程序中的每个变量都应该在功能上被识别并给出正确的类型.

它意味着使用编程开发索引然后应该创建size_t类型的一个新的结果值,特别是如果逻辑依赖于潜在符号的整数值逻辑的任何代码?

一点也不.首先,如果变量永远不会有负值,那么它可能已经unsigned int或者size_t首先出现.其次,如果变量可以计算过程中有负值,那么你一定要确保在年底它的非负的,因为你不应该用指标为负数的数组.

也就是说,如果您确定您的索引是非负的,那么将其转换为size_t没有任何区别.C11在6.5.2.1说(强调我的):

后缀表达式后跟方括号中的表达式[]是数组对象元素的下标名称.下标操作符的定义[]E1[E2]相同(*((E1)+(E2))).由于适用于binary +运算符的转换规则,if E1是一个数组对象(等效地,指向数组对象的初始元素的指针)并且E2是一个整数,E1[E2]指定E2th元素E1(从零开始计数).

这意味着任何类型的index针对some_pointer + index有意义的,允许被用作索引.换句话说,如果您知道自己int有足够的空间来容纳正在计算的索引,则绝对不需要将其转换为其他类型.


Lun*_*din 5

当然,如果下一个迭代数组的任务使用一个 unsigned int 作为索引数组,那么使用面向未来和适当大小的 size_t 定义数组长度是毫无意义的

是的。所以不要这样做。

事实上,在这种情况下,我可能希望语法严格应该将 unsigned int 上转换为关系运算符的 size_t 。

它只会在该特定<操作中被提升。int 变量的上限不会改变,因此 ++ 操作将始终使用 int 而不是 size_t。

这是否意味着迭代器变量 i 应该只是一个 size_t?

这是否意味着任何程序中的任何整数都必须在功能上标识它是否会被用作数组索引?

是的,它比 int 更好......但是有一种更聪明的方式来编写程序:使用常识。每当您声明一个数组时,您实际上可以停下来并提前考虑该数组可能需要存储多少项。如果它永远不会包含超过 100 个项目,那么您绝对没有理由使用int或使用size_t它来建立索引。

在 100 项的情况下,只需使用uint_fast8_t. 然后该程序针对大小和速度进行了优化,并且 100% 可移植。

每当声明一个变量时,一个优秀的程序员都会激活他们的大脑并考虑以下几点:

  • 我将存储在此变量中的值的范围是多少?
  • 我真的需要在其中存储负数吗?
  • 对于数组,在最坏的情况下我需要多少个值?(如果未知,我是否必须使用动态内存?)
  • 如果我决定移植这个程序,这个变量是否有任何兼容性问题?

与糟糕的程序员相反,他们不会激活他们的大脑,而只是int到处打字。