我想我们都同意,通过以一维方式解引用(可能是偏移的)指向其第一个元素的指针来访问真正的多维数组被认为是惯用的C,例如:
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);
Run Code Online (Sandbox Code Playgroud)
然而,我的语言律师需要说服这实际上是明确定义的C!特别是:
是否标准保证编译器不会把填充例如,在中间mtx[0][2]和mtx[1][0]?
通常,索引关闭数组的末尾(除了结尾之外)是未定义的(C99,6.5.6/8).所以以下内容显然是未定义的:
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];
Run Code Online (Sandbox Code Playgroud)
因此,根据相同的规则,人们会期望以下内容未定义:
int mtx[5][3];
int (*row)[3] = &mtx[0]; // The object in question is still an int[3]
int *p = &(*row)[7]; …Run Code Online (Sandbox Code Playgroud)我想创建类库,一个函数,其参数是一个未知大小的矩阵,用户将创建自己的矩阵并使用自己的大小并将其传递给此函数,对其矩阵进行一些操作,如下所示,将是功能
calculateDeterminantOfTheMatrix( int matrix[][])
{
some Operations to do on matrix
}
Run Code Online (Sandbox Code Playgroud) 来自C标准的未定义行为的示例之一(J.2):
- 数组下标超出范围,即使一个对象显然可以使用给定的下标访问(如左边的表达式a [1] [7],给出声明int a [4] [5])(6.5.6)
如果声明从更改int a[4][5]为unsigned char a[4][5],访问a[1][7]仍会导致未定义的行为吗?我的意见是,它没有,但我从其他人那里听到了不同意见,我想看看其他一些想成为专家的想法.
我的推理:
根据6.2.6.1第4段和第6.5段第7段的通常解释,对象的表示a是sizeof (unsigned char [4][5])*CHAR_BIT位,可以作为unsigned char [20]与对象重叠的类型数组进行访问.
a[1]将type unsigned char [5]作为左值,但在表达式中使用(作为运算[]符的操作数,或等效地作为运算+符的操作数*(a[1]+7)),它衰减为类型的指针unsigned char *.
值a[1]也是指向a表单中"表示"的字节的指针unsigned char [20].以这种方式解释,添加7 a[1]是有效的.