是不是double 相当于** double?
我问这是因为我的程序有两个函数来乘以matrix,他们只乘以4×4和4x1matrix。 标题是:
double** mult4x1(double **m1, double **m2); double** mult4x4(double **m1, double **m2);
他们做m1 * m2并返回一个**双,下面是一个4×4乘法片段。
double** mult4x4(double **m1, double **m2){ double** result = (double**) malloc(sizeof(double)*4); for (int i = 0; i < 4; i++) { result[i] = (double*) malloc(sizeof(double)*4); } ...multiply... return result; }
mult4x1和mult4x4之间的区别仅在它们内部使用的索引中。
我有这3个matrix:
double m1[4][4] = { {2, 3, 5, 6}, {9, 8, 1, 7}, {5, 4, 3, 1}, {7, 6, 1, 2} }; double m2[4][4] = { {1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }; double m3[4][1] = { {2}, {3}, {3}, {1} };
试图乘这些matrix发生错误。
double** test = mult4x4(m1, m2); double** test2 = mult4x1(identity4x4(), m3); //identity4x4() creates a 4x4 identity matrix - double** identity4x4();
产量:
错误:无法将
double (*)[4]' to
double * '作为参数 1'double * mult4x4(double * ,double *)'错误:无法将
double (*)[1]' to
double * '作为参数 2'double * mult4x1(double * ,double *)'
是不是double [] []应该等于** double? double数组的数组。 任何澄清,误解和错误是值得欢迎的。
没有。
double**
是指向double( double*
)的指针。
所以实际上它应该像这样创build(注意第一个malloc sizeof()中的*):
double** result = (double**) malloc(sizeof(double*)*4); for (int i = 0; i < 4; i++) { result[i] = (double*) malloc(sizeof(double)*4); }
所以在内存中它看起来像这样:
[] -> { d,d,d,d } [] -> { d,d,d,d } [] -> { d,d,d,d } [] -> { d,d,d,d }
有4个缓冲区可以容纳4个双打,但不是连续的。
而你的double [4] [4]是内存中的连续缓冲区,像这样:
{ { d,d,d,d } { d,d,d,d } {d,d,d,d} {d,d,d,d} }
尽pipedouble[N][M]
和double**
可以处理二维数组,但二者绝对不是等价的:前者表示double
s的二维数组,后者表示指向double的指针, (用C / C ++方便的方括号语法的帮助) 解释为指向double
的指针数组,或者作为double
数组数组。
double[N][M]
表示“矩形”形状的二维数组,而double**
让您通过为matrix的每一行分配不同数量的内存来构build“自由forms”(锯齿形)数组。
与编译器的区别在于给定double[N][M]
和一对整数{r,c}
它可以通过计算数组原点的偏移量来计算元素的位置,而不需要从内存中读取任何内容。 但是,给定一个double**
,编译器必须计算指向某一行的指针的地址,读取该指针,然后计算目标元素的地址。 由于这种差异,两者不能互换。
没有types[][]
。 你所拥有的实际上是m2
,它是doubletypes的大小为4的数组的arrays,而m1
是大小为1的数组的arrays。大小为4的数组的数组不等于双指针。
那么我希望我不会在这里变成愚蠢的,但是当你正在寻找一个连续的内存块时,也使用了double [][]
符号,而double**
不一定是连续的。
我认为这是错误背后的原因。 即使您可以使用相同的语义来访问值,它们实际上是不同的types。
[] []不等于**; double ** var;
是指针的指针,正如你可以从你的内存分配中看到的,你持有一个指针数组,每个指针指向一个数组double
double var [4][4];
被记忆在地方,有点相当于double *。 在这种情况下,知道matrix的大小(4 x 4),所以当你使用var[2][2]
,它知道位于内存中的位置; var[x][y]
翻译成如下forms: var[x + y * 4]
并且声明可以被解释为double var [16];
Raxvan。
不… m1
是一个有四个元素的数组,每个元素是一个由四个元素组成的数组。 与m2
相同。 即使第一个“级别”从数组衰减到指针,第二个“级别”不会。 问题是为什么? 我们来看一些代码:
/* double[4][4] implicitly converts to double(*)[4] * giving you a pointer to first element of m1 so * you get back an array of four doubles. */ double (*pm1a)[4] = m1[0]; /* This isn't right, but let's pretend that it was * and that what you got back was a pointer * to a pointer that pointed to m1 properly. */ double **pm1b = (double **)m1[0];
那么,如果我们要做pm1a[1]
和pm1b[1]
假设的代码会发生什么?
pm1a[1]
很好:它会正确地将pm1a
提前4 * sizeof(double)
(因为指针指向double[4]
)。
另一方面, pm1b[1]
会破坏:它会以错误的数量前进:指向double的指针的大小。
但这不是全部。 还有一个更微妙的错误。 如果两个维度都衰减,编译器就不知道数组正在被访问。 它会愉快地将pm1b[1]
解释为指向双pm1b[1]
的指针 。 然后会发生什么? 它会采取任何double
价值存储在该位置,并把它作为一个double
指针 。
你可以看到为什么这会是一场灾难。
不它不是。 double[n][m]
为您的二维数组分配一个足够大的内存块。 然后,您便可以不必计算自己的索引。 将二维数组传递给函数时,编译器要求您提供内部维度的大小,以便可以计算索引。
double**
是一个指针指针。 因为C允许指针算术,所以它可能意味着一个指针数组,每个指针指向一个双精度数组。 值本身不需要驻留在连续的内存块中。 正如你所看到的,他们是完全不同的野兽。
如果你有一个double[n][m]
并且想把它传递给double **
你将需要构造你自己的索引数组。
另一个区别是,如果你把它声明为double [] [](就像final字段),你不能把double指向任何其他的内存地址,
但是,如果您将其声明为** double,那么它可以指向任何内存位置。
不,它们绝对不是等价的,前者表示二维数组,而后者表示指向double的指针。