问题描述
我想我们大家都同意,这被认为是地道下用在一维的方式间接引用(可能偏移)指向它的第一个元素,例如访问一个真正的多维数组:
I imagine we all agree that it is considered idiomatic C to access a true multidimensional array by dereferencing a (possibly offset) pointer to its first element in a one-dimensional fashion, e.g.:
void clearBottomRightElement(int *array, int M, int N)
{
array[M*N-1] = 0; // Pretend the array is one-dimensional
}
int mtx[5][3];
...
clearBottomRightElement(&mtx[0][0], 5, 3);
但是,语言的律师我需要有说服力的,这实际上是良好定义的C!特别是:
However, the language-lawyer in me needs convincing that this is actually well-defined C! In particular:
-
是否标准保证编译器不会把填充在两者之间例如
MTX [0] [2]
和MTX [1] [0]
?
通常情况下,关闭索引的数组(不是一个过去的结束除外)的结束是不确定的(C99,6.5.6 / 8)。所以下面的显然是不确定的:
Normally, indexing off the end of an array (other than one-past the end) is undefined (C99, 6.5.6/8). So the following is clearly undefined:
struct {
int row[3]; // The object in question is an int[3]
int other[10];
} foo;
int *p = &foo.row[7]; // ERROR: A crude attempt to get &foo.other[4];
因此,通过相同的规则,人们所期望的以下内容是不确定的:
So by the same rule, one would expect the following to be undefined:
int mtx[5][3];
int (*row)[3] = &mtx[0]; // The object in question is still an int[3]
int *p = &(*row)[7]; // Why is this any better?
那么为什么要这样来定义?
So why should this be defined?
int mtx[5][3];
int *p = &(&mtx[0][0])[7];
那么C标准的一部分,明确允许吗? (假设为C99的就事论事。)
So what part of the C standard explicitly permits this? (Let's assume C99 for the sake of discussion.)
修改
请注意,我毫不怀疑,这工作正常在所有的编译器。我正在询问是这是否明确标准允许的。
Note that I have no doubt that this works fine in all compilers. What I'm querying is whether this is explicitly permitted by the standard.
推荐答案
要你想要做的那种访问的唯一障碍是该类型的对象 INT [5] [3]
和 INT [15]
不允许别名彼此。因此,如果编译器知道类型的指针为int *
点到的 INT [3]
阵列之一前者,可以征收数组边界的限制,将prevent访问之外的任何 INT [3]
阵列。
The only obstacle to the kind of access you want to do is that objects of type int [5][3]
and int [15]
are not allowed to alias one another. Thus if the compiler is aware that a pointer of type int *
points into one of the int [3]
arrays of the former, it could impose array bounds restrictions that would prevent accessing anything outside that int [3]
array.
您也许可以把一切既包含 INT [5] [3]
阵列和 INT [15] 数组,但我对人们是否使用类型双关工会的黑客实际上是明确的,真不清楚。因为你不会是类型夯实单个细胞,只有逻辑阵列这种情况下,可能会稍显不足问题,但我仍然不能确定。
You might be able to get around this issue by putting everything inside a union that contains both the int [5][3]
array and the int [15]
array, but I'm really unclear on whether the union hacks people use for type-punning are actually well-defined. This case might be slightly less problematic since you would not be type-punning individual cells, only the array logic, but I'm still not sure.
这是应当注意的一个特殊情况:如果你的类型是 unsigned char型
(或字符
键入)访问多维阵列作为一维阵列将被完全明确。这是因为无符号字符
重叠它明确地由标准作为对象的重新presentation限定,并且固有地允许的一维阵列别名它。
One special case that should be noted: if your type were unsigned char
(or any char
type), accessing the multi-dimensional array as a one-dimensional array would be perfectly well-defined. This is because the one-dimensional array of unsigned char
that overlaps it is explicitly defined by the standard as the "representation" of the object, and is inherently allowed to alias it.
这篇关于一维访问多维数组:定义良好的C 2的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!