且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将 T[][] 转换为 T*

更新时间:2023-02-14 13:08:24

演员表本身很好.可能确实有问题的是使用指向一个子数组中元素的指针来访问另一个子数组中的元素:虽然该操作在较低级别明确定义良好(一切都正确对齐,没有填充,类型匹配,...),我对 C 标准的印象是它的措辞允许边界检查实现符合标准.

The cast itself is fine. What might indeed be questionable would be using a pointer to an element within one subarray to access elements in a different one: While the operation is clearly well-defined at a lower level (everything's aligned properly, no padding, the types match, ...), my impression of the C standard has been that it is worded in a way that allows bounds-checking implementations to be standards-conforming.

但是请注意,线性遍历多维数组可能仍然是允许的,因为指向子数组(通常不能取消引用)的指针也恰好是指向下一个子数组的第一个元素的指针.这种想法导致指针算术是非关联的:

Note, however, that linearly traversing a multi-dimensional array might nevertheless still be permissible as a pointer pointing past a subarray (which normally must not be dereferenced) also happens to be a pointer to the first element of the next subarray. What this thought leads to is pointer arithmetics being non-associative:

据我所知,诸如 (int *)arr + 13 之类的表达式涉及未定义的行为1,但如果将其拆分为两个,则可能会变得明确步骤 ((int *)arr + 10) + 3.

It is my understanding that an expression such as (int *)arr + 13 involves undefined behaviour1, but might become well-defined if you split it into two steps ((int *)arr + 10) + 3.

如果你确实想一步完成,当然也可以选择降到字节级别,即 (int *)((char *)arr + 13 * sizeof (int)),与其他指针类型相比,这应该没有问题,字符指针受最外层封闭对象的限制.

If you do want to do it in a single step, there's of course also the option of dropping to the byte level, ie (int *)((char *)arr + 13 * sizeof (int)), which should be unproblematic as in contrast to other pointer types, character pointers are bounded by the outermost enclosing object.

我之前讨论过这个问题,但我不记得是否有明确的结论来解决这个特殊的歧义.

I've had discussions about this before, but I don't remember if there ever was a definitive conclusion resolving this particular ambiguity.

1 C11,第 6.5.6 节 §8

1 C11, section 6.5.6 §8

[...] 如果指针操作数和结果都指向同一个数组对象的元素,或者数组对象的最后一个元素之后,求值不会产生溢出;否则,行为未定义.[...]

[...] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. [...]