C 在运行时将一维数组视为二维数组
我有一些数据存储在一个一维数组中,大小为“M”。现在我需要将其视为一个二维数组,其维数为NxP,其中N和P的乘积等于M。我只在运行时知道N和P的值。如何在C中实现这样一个函数C 在运行时将一维数组视为二维数组,c,arrays,C,Arrays,我有一些数据存储在一个一维数组中,大小为“M”。现在我需要将其视为一个二维数组,其维数为NxP,其中N和P的乘积等于M。我只在运行时知道N和P的值。如何在C中实现这样一个函数 int array[M]; /* one dimensional array where some data is stored*/ int** newArray; /* the dimension of newArray should be NxP such that we can access the data in
int array[M]; /* one dimensional array where some data is stored*/
int** newArray; /* the dimension of newArray should be NxP such that we can access the data in 'array' as a two-dimensional array*/
您不需要定义新数组。您可以使用现有的 假设您知道N和p,并且N是行数,您可以访问项(i,j),如下所示:
你可以这样做:
int ** newArray = malloc(sizeof(int*) * N);
for (i = 0; i < N; ++i) {
newArray[i] = array[i * J];
}
int**newArray=malloc(sizeof(int*)*N);
对于(i=0;i
这将使一个数组“看起来”就像动态分配的由N行和J列组成的2D数组,但实际上指向1D数组的行
这样,如果您已经有函数在2D数组上运行,则无需重写它们以使用其他答案中描述的1D语法。运行时会使这一点变得更困难,但是:-
newArray = malloc( sizeof( int*) * N ); /* create an array of pointers.
{
size_t i;
for( i = 0; i < N; i++ ) {
newArray[i] = &array[ i* P];
}
}
newArray=malloc(sizeof(int*)*N);/*创建一个指针数组。
{
尺寸i;
对于(i=0;i
/*现在newArray[i][j]可用*/只需将其强制转换为适当的数组指针类型:
int (*newArray)[N] = (int (*)[N])array;
之后,您可以通过以下方式访问阵列:
for(int y = 0; y < P; y++) {
for(int x = 0; x < N; x++) {
array[y][x] = 42;
}
}
for(int y=0;y
这相当于以下索引:
for(int y = 0; y < P; y++) {
for(int x = 0; x < N; x++) {
newArray[y*N + x] = 42;
}
}
for(int y=0;y
即使只有在C99之后的运行时才知道
N
,这也可以工作。请注意,您不需要这样设置索引数组,如果使用int**
则必须这样做,您可以将1d数组强制转换为所需的2d数组。这只是一块内存
int _tmain(int argc, _TCHAR* argv[])
{
int oneDArray[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
int(*twoDArray)[3] = (int(*)[3])&oneDArray[0]; // This is the magic line!
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
printf("i: %d j: %d value: %d\r\n", i, j, twoDArray[i][j]);
}
}
_getch();
return 0;
}
int-tmain(int-argc,_-TCHAR*argv[]
{
int oneDArray[12]={0,1,2,3,4,5,6,7,8,9,10,11};
int(*twoDArray)[3]=(int(*)[3])&oneDArray[0];//这是一条神奇的线!
对于(int i=0;i<4;i++)
{
对于(int j=0;j<3;j++)
{
printf(“i:%d j:%d值:%d\r\n”,i,j,twoDArray[i][j]);
}
}
_getch();
返回0;
}
另见问题
这样做有一些内在的不安全性,但是你的问题表明NxP=M,所以如果这是真的,它会起作用。人们会皱眉。< /P>“我如何在C中实现这样的函数?”——THSULY,删除C++标签。@ WOZKRAIG:谢谢编辑。如果<代码> N>代码>行数,索引方程是错误的。如果是列数,则是正确的。感谢您的回复。但我想访问它作为二维数组与两个索引。谢谢你的答复。我想避免额外的内存分配!然后在堆栈上声明它,如
int*newArray[N]代码>而不是mallocing。因为你在回答中说了int**
,所以我认为你想要malloc。请注意,如果您返回它,虽然您将不得不malloc它。感谢您的回复。我想避免额外的内存分配!是的,这是正确的方法,指向指针的指针从一开始就是错误的工具。对于3D阵列(例如,array[X][Y][Z]
),这会是什么情况?我尝试了int(*newArray)[X][Y]=(int(*)[X][Y])array
,它不起作用:-/@ijverig这是错误的:它是指针中省略的最外面的维度。因此,对于维度顺序数组[X][Y][Z]
,您需要删除[X]
:int(*newArray)[Y][Z]=(int(*)Y][Z])数组
@ijverig注意,我们通常在C:数组[Z][Y][X]
中使用相反的维度顺序,因此int(*newArray)[Y][X]=(int(*)Y][X])数组
这样,我们将数组[z][y]
中一行的所有X
值存储在一起。我当天的投票限额已超过,但如果没有,我会加上一个:)谢谢你的这个小把戏,确保你明白发生了什么。c中的指针只是内存,所以可以将其视为包含任何内容。但是如果你把索引弄错了,c不在乎你读的内容是否超过了实际分配的末尾,这是人们对c/c++最大的抱怨,这就是缓冲区溢出。我的意思是,c在结构对齐方面有很多陷阱,有时东西放在哪里并不直观,例如,请看这里,但我猜数组总是连续的,因此在您的示例中,转换为*int[3]
是可以的。关键是int[12]
与int
边界对齐,否则偏移量总是一个线性级数(如果不是这样的话,通常取消对数组的引用会慢得多)。我认为即使使用struct foo[12],您的技巧也可以
如果您的数据类型在两个数组定义中保持不变,您就不必担心它的存储方式,因为编译器知道int是x字节,所以索引0是字节0,索引1是字节(1 x sizeof(int))等等,如果您做了一些疯狂的事情,比如将阵列保存到磁盘,然后在具有不同体系结构的计算机上重新加载它,而该体系结构对int的定义不同,那么您就会遇到问题。(非常确定INT在不同的体系结构上可以有不同的大小。)
int _tmain(int argc, _TCHAR* argv[])
{
int oneDArray[12] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
int(*twoDArray)[3] = (int(*)[3])&oneDArray[0]; // This is the magic line!
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
printf("i: %d j: %d value: %d\r\n", i, j, twoDArray[i][j]);
}
}
_getch();
return 0;
}