In this blog entry by Andrey Karpov entitled, "About size_t
and ptrdiff_t
" he shows an example,
for (ptrdiff_t i = 0; i < n; i++)
a[i] = 0;
However, I'm not sure if that's right, it seems that should be
for (size_t i = 0; i < n; i++)
a[i] = 0;
Is this correct?
I know we should also likely be using something like memset
, but let's avoid that entirely. I'm only asking about the type
In a blog post, I argue that you should always refrain from allocating memory blocks larger than PTRDIFF_MAX
(*), because doing so will make compilers such as Clang and GCC generate nonsensical code even if you do not subtract pointers to that block in a way that causes the result to overflow.
(*) Even if malloc
succeeds when you pass it a value larger than PTRDIFF_MAX
. The crux of the problem is that GCC and Clang only generate code that behaves correctly when linked with such a malloc
, but Glibc provides a malloc
function that does not implement this limitation.
If you follow that constraint (which I encourage you to: that's the message of the blog post), then both types are equally correct.
This said, since only positive offsets need to be represented, size_t
would be the natural choice in your example.
Use of ptrdiff_t
is ok since a[i]
is translated as *(a + i)
.
If you take two pointers, p1
and p2
, it is encouraged that you use:
ptrdiff_t d = p2 - p1; // Assuming p2 - p1 is valid.
Given that, p2 == p1 + d
, i.e. <ptr type> + ptrdiff_t
is a valid expression. Whether ptrdiff_t
or size_t
is better as the index type is a matter of opinion and/or coding style used in a team.
The answer to the OP's question is yes, size_t is most appropriate for the example code, where no pointer values are being subtracted from each other, and there are no cross-compiler/library compatibility issues around malloc
behaviors. Regardless of difference in heap managers, in C, an array can be SIZE_MAX
bytes in length and that requires a size_t
to represent it. Nothing in the standard requires a heap manager to be able to allocate all of a process memory space in the heap, or to allocate up to SIZE_MAX
bytes for that matter, but an array can be SIZE_MAX
in length, hence size_t
is appropriate.
Even if n
is signed, using a ptrdiff_t
for i
isn't going to help, as the initial i < n
test will fail anyway, if n
is negative, because i
is initialized to zero. There is no index into i
that a size_t
index cannot access. The only place that ptrdiff_t
is needed, is where you subtract one pointer value from another, and the OP isn't asking about that.
来源:https://stackoverflow.com/questions/51227140/for-iterating-though-an-array-should-we-be-using-size-t-or-ptrdiff-t