假设我有两个指向char
指向开头,begin,就在结束时,end,某种类型的数组(例如,按照 C++ 中范围之前的惯例)。人们期望我需要做的就是计算所述数组的大小(以字节为单位)end − begin.
然而,最新的 ISO C 标准对此有以下说明(在 §6.5.6 第 9 段中,重点是我的):
当两个指针相减时[...],结果是两个数组元素的下标之差。结果的大小是实现定义的,其类型(有符号整数类型)是ptrdiff_t
定义在<stddef.h>
标头。如果结果无法用该类型的对象表示,则行为未定义。
等效措辞一直存在于 ANSI C §6.3.6 中。
This seems to be a problem, and not an entirely theoretical one, both on systems with 16-bit size_t
and ptrdiff_t
where one would want to handle arrays of size ≥ 215, and on systems with 32-bit size_t
and ptrdiff_t
where one does occasinonally want to handle arrays of size ≥ 231 (e.g. on a 32-bit Windows server running with /3GB
).
(The first case has been made non-conforming by C99 requiring ptrdiff_t
to hold values up to at least 216 − 1, but that requirement has been widely ignored http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2808.htm on embedded systems. The second is somewhat complicated by GCC and Clang in their default configurations silently miscompiling https://trust-in-soft.com/blog/2016/05/20/objects-larger-than-ptrdiff_max-bytes/ 32-bit code that links to malloc
succeeding with ≥ 231 bytes. But I’d argue that both are still reasonable things to want to do.)
事实上,无法从 (begin, end) 通过减去是由 ISO C 标准的现任编辑给出 https://thephd.dev/_vendor/future_cxx/papers/C%20-%20Restartable%20and%20Non-Restartable%20Character%20Functions%20for%20Efficient%20Conversions.html#design-forms-simplify以避免添加采用此类对的 API。 (不过,与 C++ 不同,此类 API 对于 C 标准库来说无论如何都是不常见的。)
So, is有一个O(1) 计算任意大小物体大小的方法(begin, end) 严格符合 ISO C 程序中的指针?你总是可以做size_t size = 0; while (begin++ < end) size++;
as an O(size)当然是解决方案,但这似乎很愚蠢,即使现代优化编译器可以解决这个问题。