一维访问多维数组:定义良好的C 2 [英] One-dimensional access to a multidimensional array: well-defined C?

查看:100
本文介绍了一维访问多维数组:定义良好的C 2的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想我们大家都同意,这被认为是地道下用在一维的方式间接引用(可能偏移)​​指向它的第一个元素,例如访问一个真正的多维数组:

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:


  1. 是否标准保证编译器不会把填充在两者之间例如 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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