Cyt*_*sis -1 c pointers pointer-arithmetic multidimensional-array
我需要帮助理解如何在C中使用点算法来计算二维数组.我正在使用这个网站(http://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/)作为参考(使用示例1) ,一个指针).
int numRows = 2;
int numColumns = 3;
double * arrayMatrix = malloc(numRows * numColumns * sizeof(double));
int row = 0;
int column = 0;
printf("\nPlease enter the elements of your augmented matrix:\n");
for(row = 0; row < numRows; row++)
{
for(column = 0; column < numColumns; column++)
{
printf("A[%d][%d]:", row + 1, column + 1);
scanf("%lf", &arrayElement);
printf("\n");
*(arrayMatrix + row * numColumns + column) = arrayElement;
//arrayMatrix[row + numColumns + column] = arrayElement;
}
}
// TEST PRINT
for(row = 0; row < numRows; row++)
{
for(column = 0; column < numColumns; column++)
{
printf("%5.2lf", *(arrayMatrix + row * numColumns + column));
//printf("%5.2lf", arrayMatrix[row + numColumns + column]);
}
printf("\n");
}
Run Code Online (Sandbox Code Playgroud)
我需要帮助理解这是否是将数据输入2D数组的正确方法,以及它是否也是从2D数组打印数据的正确方法.我将第1行的示例数据用作{1,2,3},将第2行用作{1,2,3}; 但是当打印出所有6个元素时,我得到的信息都是0.
我也用这个答案作为参考(如何使用指针表达式来访问C中二维数组的元素?).具体遵循以下这一行:
int x = *((int *)y + 2 * NUMBER_OF_COLUMNS + 2); // Right!
Run Code Online (Sandbox Code Playgroud)
但我使用的是双指针而不是整数,但我不知道这是否会导致我的问题,或者是否是其他问题.
编辑 - 稍微更新了代码,但它仍然无法正常工作.
编辑2:这是我最近尝试开始工作的代码的最新更新.从阵列输入和打印数据的所有3种方式都会产生相同的结果(数组中所有值都为0).
int numRows = 2;
int numColumns = 3;
//double * arrayMatrix = malloc(numRows * numColumns * sizeof(double));
double (*arrayMatrix)[numColumns] = malloc(sizeof(double[numRows][numColumns]));
int row = 0;
int column = 0;
printf("\nPlease enter the elements of your augmented matrix:\n");
for(row = 0; row < numRows; row++)
{
for(column = 0; column < numColumns; column++)
{
printf("A[%d][%d]:", row + 1, column + 1);
scanf("%lf", &arrayElement);
printf("\n");
//*(arrayMatrix + row * numColumns + column) = arrayElement;
//arrayMatrix[row + numColumns + column] = arrayElement;
arrayMatrix[row][column] = arrayElement;
}
}
// TEST PRINT
for(row = 0; row < numRows; row++)
{
for(column = 0; column < numColumns; column++)
{
//printf("%5.2lf", *(arrayMatrix + row * numColumns + column));
//printf("%5.2lf", arrayMatrix[row + numColumns + column]);
printf("%5.2lf", arrayMatrix[row][column]);
}
printf("\n");
}
Run Code Online (Sandbox Code Playgroud)
我想我明白你想做什么.在我们讨论代码之前,让我们回顾一下并稍微了解一下可以在C中模拟2D数组的不同方法.您有两种基本方法.您可以静态或动态声明一个数组array[row][col] = {{r0c0, r0c1, r0c2, ...}, {r1c0, r1c1, r1c2, ...} ... };,该数组将创建一个单独的内存块,并按顺序存储这些值r0c0, r0c1, r0c2, ..., r1c0, r1c1, r1c2, ...,或者您可以创建row指针数,每个指针指向一个单独的col元素数组.第二种方法(row每个指向col元素数组的指针数)不需要在内存中顺序.它可以,但没有要求它.
数组索引表示法array[i][j]将负责处理顺序内存块中的偏移量,以提供对任何单个元素的访问.对于访问指向的单个col大小数组内的任何元素也是如此array[i].但究竟发生了什么?
让我们来看一个简单的4元素数组的符号array[4].要访问任何元素,你可以要求任何元素array[0]来array[3]访问所有4个元素.array[2]真的是什么?你知道array也是一个指针.您知道要访问指针所占地址的值,您需要取消引用指针.要访问array[0],您可以简单地编写*array,但是如何使用指针表示法访问第二个元素?
正如我们前面讨论的那样,声明为我们声明此示例的数组中的所有元素都按顺序存储在内存中.因此,要访问数组中的任何元素,您只需要从数组开头的偏移量.既然你知道数组的起始地址就是array,如果你想要第二个元素,你需要1从头开始访问元素偏移,或者*(array + 1)- 尝试它.实际上,您可以0-3从头开始访问所有元素,*(array + i)其中i的数字位于0-3.
回顾一下,这也解释了为什么你可以通过简单地使用来访问数组中的第一个元素*array.如果你为第一个元素编写了完整的语法*(array + 0)- 你知道+ 0它什么都不做,这就是为什么你可以使用*array因为访问第一个元素*(array + 0) = *array.
好的,2D案例怎么样?如果array[x]是*(array + x),那是array[x][y]什么?分解.你知道你可以写array[x]的*(array + x),所以array[x][y]可以写*(array + x)[y](如果我们替换stuff了*(array + x)的那一刻,我们可以写stuff[y]我们知道如何写在指针符号:*(stuff + y)?,现在刚刚替补*(array + x)了stuff,你会得到*(*(array + x) + y),这是你的全用于以模拟的2D数组方式访问顺序内存块中的任何元素的指针表示法,这是在您编写时在场景后面发生的事情array[x][y].
现在让我们谈谈指针算术.声明指针时,您将声明指向特定的指针type(除非是void).这type告诉编译器如何使用该指针处理算术.例如,如果您声明:
char array[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
char *p = array;
Run Code Online (Sandbox Code Playgroud)
编译器知道每个char占用1-byte的内存,所以当你写*(p + 1),你要求从一开始的char值.如果你写的话也是如此.但是会发生什么:1-bytearrayp++;*p
int array[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
int *p = array;
Run Code Online (Sandbox Code Playgroud)
由于知道typeis int和a int是4-bytes(平台相关的),当你编写*(p + 1)或者p++; *p;,你将得到数组中的第二个元素,但是值是4-bytes从数组的开头.该type告诉编译器如何处理指针运算(即偏移对于任何给定值).
你可以用一个最小的例子来解决这个问题:
#include <stdio.h>
#define ROWS 2
#define COLS 2
int main (void) {
int a[ROWS][COLS] = {{ 1, 2 }, { 3, 4 }};
int *p = *a;
int i, j;
for (i = 0; i < ROWS; i++) {
for (j = 0; j < COLS; j++)
printf (" %2d", a[i][j]);
putchar ('\n');
}
/* using a pointer to access the values */
for (i = 0; i < ROWS * COLS; p++, i++)
printf (" %2d", *p);
putchar ('\n');
return 0;
}
Run Code Online (Sandbox Code Playgroud)
产量
$ ./bin/array_min
1 2
3 4
1 2 3 4
Run Code Online (Sandbox Code Playgroud)
现在谈谈你实际问的问题.鉴于我们所讨论的所有内容,您宣布什么时宣布:
double (*arrayMatrix)[NCOLS] = calloc (NROWS, NCOLS * sizeof **arrayMatrix);
Run Code Online (Sandbox Code Playgroud)
你是在为什么指针声明和分配空间?指向doubles带NCOLS元素数组的指针.你有多少人需要持有完整的阵列?您将需要NROWS多个指向数组的指针,NCOLS每个数组都包含元素.注意上面使用的calloc代替malloc.语法和它们的作用都有一个重要但微妙的区别.malloc将分配内存给你,但内存未初始化,并且可以包含各种形式的东西.calloc也分配,但然后将内存初始化为零.在处理数值数组时,这对于防止意外访问未初始化元素(导致未定义的行为)非常有用.有之间的边缘速度差malloc和calloc作为结果,但你将很难找到任何小于几一个可测量的差异万元拨款.
在此背景下,再次考虑您要做的事情.只需很少的调整,如果你做了类似的事情,你就会更有意义:
#include <stdio.h>
#include <stdlib.h>
#define NROWS 2
#define NCOLS 3
int main (void) {
size_t row = 0;
size_t col = 0;
/* allocate NROWS (array of pointers to NCOLS doubles). using
* calloc will allocate and initialize all elements to zero.
*/
double (*arrayMatrix)[NCOLS] = calloc (NROWS, NCOLS * sizeof **arrayMatrix);
/* prompt user for input, validate a proper value is entered */
printf("\nPlease enter the elements of your augmented matrix:\n");
for(row = 0; row < NROWS; row++)
{
for(col = 0; col < NCOLS; col++)
{
while (printf(" A[%zu][%zu]: ", row + 1, col + 1) &&
scanf("%lf", &arrayMatrix[row][col]) != 1)
printf("\n");
}
}
/* printf the array of pointers */
printf ("\n The matrix entered was:\n\n");
for(row = 0; row < NROWS; row++)
{
for(col = 0; col < NCOLS; col++)
{
printf(" %5.2lf", arrayMatrix[row][col]);
}
printf("\n");
}
free (arrayMatrix);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
产量
$ ./bin/arraymatrix
Please enter the elements of your augmented matrix:
A[1][1]: 1
A[1][2]: 2
A[1][3]: 3
A[2][1]: 4
A[2][2]: 5
A[2][3]: 6
The matrix entered was:
1.00 2.00 3.00
4.00 5.00 6.00
Run Code Online (Sandbox Code Playgroud)
内存错误/泄漏检查
在你的动态分配内存的任何代码中,你有2个责任关于任何分配的内存块:(1)总是保留一个指向内存块起始地址的指针,所以,(2)它可以在没有时被释放需要更久.您必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,并确认已释放已分配的所有内存.对于Linux valgrind来说是正常的选择.有许多微妙的方法来滥用可能导致实际问题的内存块,没有理由不这样做.每个平台都有类似的记忆检查器.它们都很简单易用.只需通过它运行您的程序.
$ valgrind ./bin/arraymatrix
==17256== Memcheck, a memory error detector
==17256== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==17256== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==17256== Command: ./bin/arraymatrix
==17256==
Please enter the elements of your augmented matrix:
A[1][1]: 1
A[1][2]: 2
A[1][3]: 3
A[2][1]: 4
A[2][2]: 5
A[2][3]: 6
The matrix entered was:
1.00 2.00 3.00
4.00 5.00 6.00
==17256==
==17256== HEAP SUMMARY:
==17256== in use at exit: 0 bytes in 0 blocks
==17256== total heap usage: 1 allocs, 1 frees, 48 bytes allocated
==17256==
==17256== All heap blocks were freed -- no leaks are possible
==17256==
==17256== For counts of detected and suppressed errors, rerun with: -v
==17256== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
Run Code Online (Sandbox Code Playgroud)
如果您有其他问题,请与我们联系.我的手指累了.结果比我预期的要长得多......