c - C 中数组索引的正确类型是什么?

标签 c types indexing c99

C99 中的数组索引应该使用什么类型?它必须适用于 LP32、ILP32、ILP64、LP64、LLP64 等。它不一定是 C89 类型。

我找到了 5 个候选人:

  • size_t
  • ptrdiff_t
  • intptr_t/uintptr_t
  • int_fast*_t/uint_fast*_t
  • int_least*_t/uint_least*_t

有简单的代码可以更好地说明问题。在这两个特定循环中,ij 的最佳类型是什么。如果有充分的理由,两种不同的类型也可以。

for (i=0; i<imax; i++) {
        do_something(a[i]);
}
/* jmin can be less than 0 */
for (j=jmin; j<jmax; j++) {
        do_something(a[j]);
}

附言 在问题的第一个版本中,我忘记了负索引。

附言 我不会编写 C99 编译器。然而,编译器程序员的任何回答对我来说都是非常有值(value)的。

类似问题:

最佳答案

我认为你应该使用ptrdiff_t,原因如下

  • 索引可以是负数。因此对于一般性的陈述,所有无符号类型,包括size_t,都是不合适的。
  • p2 - p1 的类型是ptrdiff_t。如果 i == p2 - p1,那么你应该能够通过 p2 == p1 + i 得到 p2。请注意,*(p + i) 等同于 p[i]
  • 作为此“通用索引类型”的另一个指示,当内置 operator[](例如,在指针上)与用户竞争时,重载决策所使用的索引类型所提供的 operator[](例如 vector 的)正是(http://eel.is/c++draft/over.built#16): >

    For every cv-qualified or cv-unqualified object type T there exist candidate operator functions of the form

    T*      operator+(T*, std::ptrdiff_t);
    T&      operator[](T*, std::ptrdiff_t);
    T*      operator-(T*, std::ptrdiff_t);
    T*      operator+(std::ptrdiff_t, T*);
    T&      operator[](std::ptrdiff_t, T*);
    

编辑:如果你有一个真的大数组或指向一个非常大的内存部分的指针,那么我的“通用索引类型”不会削减它,因为它不能保证您可以从最后一个元素的地址中减去第一个元素的地址。然后应该使用@Ciro 的回答https://stackoverflow.com/a/31090426/34509 .就我个人而言,我尽量避免使用无符号类型,因为它们无法表示负面的边缘情况(例如,向后迭代时循环结束值),但这是一种宗教辩论(不过我并不孤单) .当然,在需要使用无符号类型的情况下,我必须抛开我的宗教信仰。

关于c - C 中数组索引的正确类型是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3174850/

相关文章:

rust - 类型组的通用枚举

sql - 对分区表使用分区索引

c# - 从 C# 访问 C DLL 结构中的数组

c - 关于下面给出的查询的输出

c - 这个嵌套循环的简单解释是什么

MySQL:使用自然主索引或在给定表时添加代理索引

Mysql subselect 非常慢(似乎没有使用索引)

c - C99 Keil MDK5 中的匿名结构、 union

c - C 类型之间的区别 int32_t int_least32_t 等

c++ - 如何在 C++ 中存储 1000000 位整数