I am working on some computational physics problems in C and I face some confusion regarding my code. I spent the last weeks reading about C but I'm still new to this language.
我正在研究C中的一些计算物理问题,我对代码有些困惑。我花了最后几个星期阅读关于C的文章,但我仍然对这门语言不熟悉。
I need to work on a two dimensional array. The length of each row may vary, so for example, I might want to use: create and modify a "triangle" matrix: [[0,1,2][1,2][2]]
.
我需要处理二维数组。每行的长度可能会有所不同,例如,我可能想要使用:创建和修改“三角形”矩阵:[[0,1,2] [1,2] [2]]。
In order to structure my code in a way that is maintainable, easy to read and modify, I wanted to move parts of the logic to a function. However, it appears to be more difficult than I expected.
为了以可维护,易于阅读和修改的方式构造我的代码,我想将部分逻辑移动到一个函数中。但是,它似乎比我预期的更困难。
I started with an approach where I create a int **matrix
variable and pass it to a function, prefixing it with an ampersand and accept a three-star int: int ***
, and work with the matrix as *matrix[i][j]
. I couldn't get it to work, however matrix[0][i][j]
worked and I just can't get my head around it. Aren't the two notions the same?
我从一个方法开始,我创建一个int **矩阵变量并将其传递给一个函数,在它前面添加一个&符号并接受一个三星的int:int ***,并使用矩阵作为* matrix [i] [J]。我无法让它工作,但矩阵[0] [i] [j]工作,我只是无法理解它。这两个概念不一样吗?
Here is my code:
这是我的代码:
void alloc_subscript_notation(int number_of_rows, int *** matrix) {
matrix[0] = malloc(number_of_rows * sizeof(int *));
for (int i = 0; i < number_of_rows; i++)
matrix[0][i] = calloc((number_of_rows-i), sizeof(int));
}
void modify_subscript(int number_of_rows, int *** matrix) {
matrix[0][0][1] = 8; // just set a value of an element to 8, as a proof of concept
}
void subscript_notation (int number_of_rows, int *** matrix) {
alloc_subscript_notation(number_of_rows, matrix);
modify_subscript(number_of_rows, matrix); // I can even modify it
}
void alloc_star_notation(int number_of_rows, int *** matrix) {
*matrix = malloc(number_of_rows * sizeof(int *));
for (int i = 0; i < number_of_rows; i++)
*matrix[i] = calloc((number_of_rows-i), sizeof(int));
printf("alloc_subscript_notation: zeros: %d, %d, %d\n", // just a few examples
*matrix[0][2], *matrix[1][1], *matrix[2][0]);
}
void star_notation (int number_of_rows, int *** matrix) {
// SEGMENTATION FAULT!!!
alloc_star_notation(number_of_rows, matrix);
}
int main (void) {
int ** matrix;
int number_of_rows = 3; // it's dynamic in my program, but I use it this hard-coded value for clarity
// I want to be able to access matrix elements here
// All good here.
subscript_notation(number_of_rows, &matrix);
printf("subscript_notation ready. main: "
" %d, %d, %d, modified: %d\n",
matrix[0][2], matrix[1][1], matrix[2][0], matrix[0][1]);
// Segmentation Fault
star_notation(number_of_rows, &matrix);
}
4 个解决方案
#1
2
No, *matrix[i][j]
and matrix[0][i][j]
are not the same.
不,* matrix [i] [j]和matrix [0] [i] [j]不一样。
The former is identical to *(matrix[i][j])
, whereas the latter is identical to (*matrix)[i][j]
.
前者与*(matrix [i] [j])相同,而后者与(* matrix)[i] [j]相同。
Since you're trying to access the pointer which was passed to the function using the address operator, you have to use the latter version.
由于您尝试访问使用地址运算符传递给函数的指针,因此必须使用后一版本。
#2
2
I couldn't get it to work, however matrix[0][i][j] worked and I just can't get my head around it. Aren't the two notions the same?
我无法让它工作,但矩阵[0] [i] [j]工作,我只是无法理解它。这两个概念不一样吗?
No, *matrix[i][j]
and matrix[0][i][j]
are different things.
不,* matrix [i] [j]和matrix [0] [i] [j]是不同的东西。
Given int *** matrix
, then matrix[i][j]
is pointer to int
, and *matrix[i][j]
is actually matrix[i][j][0]
给定int ***矩阵,则matrix [i] [j]是指向int的指针,而* matrix [i] [j]实际上是matrix [i] [j] [0]
#3
1
Just to expand the answer of @artm, you are not (strictly speaking) reserving space for a 2D array, the correct way to reserve space (without segmentation) for a 2D array in C is using a VLA:
只是为了扩展@artm的答案,你不是(严格来说)为2D数组保留空间,为C中的2D数组保留空间(没有分段)的正确方法是使用VLA:
#include <stdio.h>
#include <stdlib.h>
static void func(size_t dim, int (**matrix)[dim])
{
*matrix = malloc(sizeof(int[dim]) * dim);
}
int main(void)
{
size_t dim = 3;
int (*matrix)[dim]; /* A pointer to an array of n elements */
func(dim, &matrix);
free(matrix);
return 0;
}
#4
0
I'd suggest you to use a contiguous block of memory to simplify tour code.
我建议你使用连续的内存块来简化游览代码。
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void alloc_subscript_notation(int number_of_rows, int number_of_cols, int **matrix)
{
*matrix = malloc(number_of_rows * number_of_rows * sizeof(int));
if (*matrix != NULL)
{
for (int i=0; i<number_of_rows; i++)
{
for (int j=0; j<number_of_cols; j++)
{
(*matrix)[(i*number_of_cols)+j] = (i*number_of_cols)+j;
}
}
}
}
int main (void) {
int *matrix;
int number_of_rows = 3; // it's dynamic in my program, but I use it this hard-coded value for clarity
int number_of_cols = 3; // it's dynamic in my program, but I use it this hard-coded value for clarity
// I want to be able to access matrix elements here
// All good here.
alloc_subscript_notation(number_of_rows, number_of_cols, &matrix);
if (matrix != NULL)
{
printf("subscript_notation ready. main: "
" %d, %d, %d, modified: %d\n",
matrix[(0*number_of_cols)+2], matrix[(1*number_of_cols)+1], matrix[(2*number_of_cols)+0], matrix[(0*number_of_cols)+1]);
}
}
#1
2
No, *matrix[i][j]
and matrix[0][i][j]
are not the same.
不,* matrix [i] [j]和matrix [0] [i] [j]不一样。
The former is identical to *(matrix[i][j])
, whereas the latter is identical to (*matrix)[i][j]
.
前者与*(matrix [i] [j])相同,而后者与(* matrix)[i] [j]相同。
Since you're trying to access the pointer which was passed to the function using the address operator, you have to use the latter version.
由于您尝试访问使用地址运算符传递给函数的指针,因此必须使用后一版本。
#2
2
I couldn't get it to work, however matrix[0][i][j] worked and I just can't get my head around it. Aren't the two notions the same?
我无法让它工作,但矩阵[0] [i] [j]工作,我只是无法理解它。这两个概念不一样吗?
No, *matrix[i][j]
and matrix[0][i][j]
are different things.
不,* matrix [i] [j]和matrix [0] [i] [j]是不同的东西。
Given int *** matrix
, then matrix[i][j]
is pointer to int
, and *matrix[i][j]
is actually matrix[i][j][0]
给定int ***矩阵,则matrix [i] [j]是指向int的指针,而* matrix [i] [j]实际上是matrix [i] [j] [0]
#3
1
Just to expand the answer of @artm, you are not (strictly speaking) reserving space for a 2D array, the correct way to reserve space (without segmentation) for a 2D array in C is using a VLA:
只是为了扩展@artm的答案,你不是(严格来说)为2D数组保留空间,为C中的2D数组保留空间(没有分段)的正确方法是使用VLA:
#include <stdio.h>
#include <stdlib.h>
static void func(size_t dim, int (**matrix)[dim])
{
*matrix = malloc(sizeof(int[dim]) * dim);
}
int main(void)
{
size_t dim = 3;
int (*matrix)[dim]; /* A pointer to an array of n elements */
func(dim, &matrix);
free(matrix);
return 0;
}
#4
0
I'd suggest you to use a contiguous block of memory to simplify tour code.
我建议你使用连续的内存块来简化游览代码。
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void alloc_subscript_notation(int number_of_rows, int number_of_cols, int **matrix)
{
*matrix = malloc(number_of_rows * number_of_rows * sizeof(int));
if (*matrix != NULL)
{
for (int i=0; i<number_of_rows; i++)
{
for (int j=0; j<number_of_cols; j++)
{
(*matrix)[(i*number_of_cols)+j] = (i*number_of_cols)+j;
}
}
}
}
int main (void) {
int *matrix;
int number_of_rows = 3; // it's dynamic in my program, but I use it this hard-coded value for clarity
int number_of_cols = 3; // it's dynamic in my program, but I use it this hard-coded value for clarity
// I want to be able to access matrix elements here
// All good here.
alloc_subscript_notation(number_of_rows, number_of_cols, &matrix);
if (matrix != NULL)
{
printf("subscript_notation ready. main: "
" %d, %d, %d, modified: %d\n",
matrix[(0*number_of_cols)+2], matrix[(1*number_of_cols)+1], matrix[(2*number_of_cols)+0], matrix[(0*number_of_cols)+1]);
}
}