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

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

问题描述

将类型为T的2D数组强制转换为T*并取消引用元素是否安全?

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

由于2D数组的内存布局是线性的,因此基本指针应等于指向第一个元素的指针.由于它们指向的最终类型也相同,因此不应存在任何对齐差异问题.

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天全站免登陆