且构网

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

将T [] []强制转换为T *

更新时间:2023-02-14 12:30:14

强制转换本身很好.可能确实存在问题的是使用指向一个子数组中元素的指针来访问另一元素中的元素:尽管该操作在较低级别上定义明确(所有内容正确对齐,没有填充,类型匹配,.. ),我对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. [...]