间接运算符和数组指针
当间接寻址运算符用于多维数组时,它的常规定义似乎并不适用:
int arr[10][10][10];
如果您取消引用 arr,您将获得相同的地址:
(void*)arr == (void*)*arr && (void*)*arr == (void*)**arr
但这很有意义 - 多维数组只是一个连续的数组内存区域,指针指向内存的开头。编译器本质上会忽略取消引用,只计算正确的偏移量。使用间接运算符似乎只保留了多维数组的抽象,并使其适合该语言的其他语法结构。
如果执行以下操作:
int *** ptr = (int***) arr;
并取消引用 ptr,您将看到正常的取消引用行为,其中返回指针指定的位置中的值。使用上面的转换,如果取消引用指针两次以上,您将读入未定义的内存。
我只是想知道为什么这种行为没有在更多地方记录 - 也就是说,间接运算符对指向数组的指针与指向指针和指向值的指针的效果有何不同?
It seems the regular definition of the indirection operator doesn't apply when it is used on multi-dimensional arrays:
int arr[10][10][10];
If you dereference arr, you'll get the same address:
(void*)arr == (void*)*arr && (void*)*arr == (void*)**arr
This makes sense though - a multi-dimensional array is just a contiguous region of memory, where the pointer points at the beginning of the memory. The compiler essentially ignores dereferences and just computes the proper offset. Use of the indirection operator seems to only preserve the abstraction of multi-dimensional arrays and make it fit with the other syntactic constructs of the language.
If you do the following:
int *** ptr = (int***) arr;
And dereference ptr, you'll see the normal dereference behavior, where the value in the location specified by the pointer is returned. Using the above cast, you'll read into undefined memory if you dereference the pointer more than twice.
I'm just wondering why this behavior isn't documented in more places - that is, the difference of effect of the indirection operator on pointers to arrays vs pointers to pointers and pointers to values?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,要完全理解这一点,您必须认识到 C 没有多维数组 - 它有数组的数组。因此,在您的示例中,
arr
是“一个由 10 个数组组成的数组,每个数组由 10 个数组组成,每个数组由 10 个整数组成”。其次,行为不同的不是间接运算符,而是数组类型的表达式的行为很奇怪。
如果数组类型的表达式不是一元
&
或sizeof
运算符1的主题,那么它的计算结果是指向该数组第一个元素的指针。这意味着在以下表达式中:
在左侧,
arr
计算结果为指向arr
内第一个由 10 个 10 个整数数组组成的数组的指针(即 <代码>&arr[0])。然后取消引用以获得该数组本身:arr 中的第一个子数组,arr[0]
。但是,由于arr[0]
本身就是一个数组,因此它会被替换为指向它第一个元素的指针,&arr[0][0]
。在右侧,上述情况与左侧相同,然后取消引用最后一个指针,获得 arr[0][0]。这又是一个数组,因此最终被替换为指向其第一个元素的指针
&arr[0][0][0]
。它们相等的原因(转换为
void *
后)仅仅是因为数组arr[0][0]
的地址和 int的地址arr[0][0][0]
一致,因为后者是前者的第一个成员。它们还与arr[0]
和arr
的地址一致,因此您也有:
1. ..and is not a string literal used in an initializer.
Firstly, to fully understand this you must appreciate that C does not have multidimensional arrays - it has arrays of arrays. So, in your example,
arr
is "an array of 10 arrays of 10 arrays of 10 ints".Secondly, it's not the indirection operator that behaves differently, it's the behaviour of expressions with array type that's odd.
If an expression with array type is not the subject of either the unary
&
orsizeof
operators1, then it evaluates to a pointer to the first element of that array.This means that in the following expression:
On the left hand side,
arr
evaluates to a pointer to the first array of 10 arrays of 10 ints withinarr
(that is,&arr[0]
). This is then dereferenced to obtain that array itself: the first sub-array within arr,arr[0]
. However, sincearr[0]
is itself an array, this then is replaced with a pointer to it's first element,&arr[0][0]
.On the right hand side, the above happens as per the left hand side, then that last pointer is dereferenced, obtaining
arr[0][0]
. This, again, is an array, so it is finally replaced with a pointer to its first element,&arr[0][0][0]
.The reason these are equal (after conversion to
void *
) is simply because the address of the arrayarr[0][0]
and the address of the intarr[0][0][0]
coincide, as the latter is the first member of the former. They also concide with the address ofarr[0]
andarr
, so you also have:as well.
1. ..and is not a string literal used in an initializer.