即使数组的大小没有超过int的大小,我是否需要始终使用size_t
来索引数组?
这不是关于何时应该使用size_t
的问题。我只想知道,例如,一个程序有2GB可用内存(所有这些字段都可以通过int32进行索引),但是该内存被分配到计算机RAM的14GB - 16GB的"fields"。
如果在这种情况下使用int32
而不是size_t
(或unsigned long int
)进行索引,它是否总是会失败?
也许这个问题更与虚拟内存有关,而不是指针。
即使数组的大小没有超过int的大小,我是否需要始终使用size_t
来索引数组?
这不是关于何时应该使用size_t
的问题。我只想知道,例如,一个程序有2GB可用内存(所有这些字段都可以通过int32进行索引),但是该内存被分配到计算机RAM的14GB - 16GB的"fields"。
如果在这种情况下使用int32
而不是size_t
(或unsigned long int
)进行索引,它是否总是会失败?
也许这个问题更与虚拟内存有关,而不是指针。
size_t
是一个无符号整数,能够保存您可以分配的最大对象的大小。它非常有用于索引,因为这意味着它可以索引到您可以分配的最大数组。
但这并不意味着索引时必须或者一定建议使用它。您可以使用任何足够大的整数类型来对数组进行索引。int_fast32_t
可能更快,uint_least16_t
在结构中可能更小,等等。了解您的数据,您可以做出一个好的选择。
您应该考虑的一个问题是,在某些平台上,使用带符号索引可能需要额外的符号扩展指令。例如,这里是x86-64:
// ; zero-extending idx (in edx) is "free" by simply using rdx.
// movzx eax, BYTE PTR [rcx+rdx]
// ret
char get_index(char *ptr, unsigned idx)
{
return ptr[idx];
}
// ; sign extending idx from 32 bits to 64 bits with movsx here.
// movsx rdx, edx
// movzx eax, BYTE PTR [rcx+rdx]
// ret
char get_index(char *ptr, int idx)
{
return ptr[idx];
}
虚拟内存超出了C或C++的范围。从它们的角度来看,你只是索引到内存中,由你的平台来使其工作。实际上,你的应用程序只使用虚拟地址;你的CPU/操作系统在幕后将虚拟地址转换为物理地址。这不是你需要担心的事情。
int a[8000];
a[3] = 42;
printf("%d\n", 3[a]); // legal, and prints "42"!
您甚至可以从指向数组的指针进行索引,并使用负下标(只要引用仍在同一数组或其末尾的一个元素内)。
a[3] = 42;
int *p = a + 6;
printf("%d\n", p[-3]); // also legal, and prints "42"!
// off-topic
printf("%d\n", -3[p]); // legal, but does *not* print "42"!
size_t
总是无符号整数类型。std::vector
和 std::array
,C++ 有一些额外的细节。std::vector::size_type
。这些几乎总是与 std::size_t
相同的底层类型。std::vector<int> v = { 0, 1, 2, 3 };
std::cout << 3[v] << '\n'; // std container types cannot emulate this
// kind of array indexing
std::cout << v[3] << '\n';
3
被视为一个int
,它是有符号的且可能具有比std::size_t
-- 呃,std::vector<int>::size_type
更小的范围。希望这使得清楚,只要您使用的任何类型可以表示所需的索引,就不需要使用大小类型作为索引。operator[]
实现的。因此,3
可能是一个int
,但是为了匹配重载的定义,它将首先转换为std::vector<int>::size_type
。size_t
作为索引,而不管实际使用的类型是什么。size()
方法返回类型一样大的索引类型。这确保了索引永远不会超出数组可能的大小。数组的实现通常是确保其运行时大小不会超过size()
方法返回的类型。这意味着索引类型应该是:
char[N]
, uint8_t[N]
, int[N]
等情况下,使用size_t
std::vector
和std::list
情况下,使用size_t
QList
和QVector
情况下,使用int
size()
方法返回一个任意精度整数(aint),则使用aintsize()
方法返回一个任意精度整数(aint),则使用aintsize()
方法返回一个任意精度整数(aint),则使用aintjava.util.Collection
及其子类的情况下,使用int
总之:安全的索引类型是size()
方法返回的类型。
size()
方法返回无符号的size_t
,那么有符号的int
和ssize_t
不是安全的索引类型。在gcc和clang中,编译器标志-Wsign-compare
(通过-Wall
启用)和-Wconversion
可以用于防止大多数这种情况。
size_t
的原因是它使您的程序具有可移植性。 - Mukul Guptasize_t
确保能够索引您所投掷的任何内容的每个字节。有时很方便。 - user4581301char
是可行的选择。这与可寻址内存或虚拟内存的总量无关。如果您不知道数组大小,size_t
能够容纳任何数组的任何索引,因此非常有用。 - n. m.