将 T[][] 转换为 T* [英] Cast T[][] to T*

查看:55
本文介绍了将 T[][] 转换为 T*的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

T 类型的二维数组转换为 T* 并取消引用元素是否安全?

Is it safe to cast a 2D array of type T to T* and dereference the elements?

由于二维数组的内存布局是线性的,因此基指针应该等于指向第一个元素的指针.由于它们指向的最终类型也是相同的,所以应该没有任何对齐差异问题.

Since the memory layout of 2D array is linear the base pointer should be equal to pointer to the first element. Since the final type they are pointing to is also the same, there shouldn't be any alignment difference issue.

或者某些方面会导致未定义行为?

Or there is some aspect that can cause Undefined Behaviour?

为了清楚起见,我的意思是这样的 -

Just to be clear I mean something like this -

int arr[10][10];
int p = *((int*) arr);

另外,如果我访问第一个数组之外的元素,即 (int*) arr + 13,同样的问题.它是否属于越界访问的条款?因为我在第一个数组的边界之外访问.

Also, the same question if I access elements beyond the first array i.e. (int*) arr + 13. Would it come under the clause of out of bounds access? Since I am accessing outside the bounds of the first array.

推荐答案

演员表本身很好.可能确实有问题的是使用指向一个子数组中元素的指针来访问另一个子数组中的元素:虽然该操作在较低级别明确定义良好(一切都正确对齐,没有填充,类型匹配,...),我对 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. [...]

这篇关于将 T[][] 转换为 T*的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆