double[][] 不等于 **double?
Isn't double[][] equivalent to **double?
我问这个是因为我的程序有两个函数来乘以矩阵,它们只乘以 4x4 和 4x1 矩阵。标头为:
double** mult4x1(double **m1, double **m2);
double** mult4x4(double **m1, double **m2);
他们做 m1*m2 并以 **double 返回它,下面是 4x4 乘法的片段。
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 个矩阵:
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}
};
尝试将这些矩阵相乘时会发生错误。
double** test = mult4x4(m1, m2);
double** test2 = mult4x1(identity4x4(), m3);
//identity4x4() creates a 4x4 identity matrix - double** identity4x4();
收益 率:
双倍[]错误:无法将参数
1' to
转换为双精度*'double (*)[4]' to
双精度* Mult4x4(双精度*,双倍*)'错误:无法将参数转换为双精度*
double (*)[1]' to
2' to
双*',双倍* Mult4x1(双精度*,双倍*)'
[]不应该等于**双倍吗?双精度数组的数组。欢迎任何澄清、误解和错误。
No.double**
是指向双精度 (double*
) 的指针。
所以实际上它应该像这样创建(注意第一个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} }
虽然double[N][M]
和double**
都允许你处理 2D 数组,但两者绝对不等价:前者表示 double
s 的 2D 数组,而后者表示指向双精度的指针,可以解释为(借助 C/C++ 方便的方括号语法)作为指向 double
的指针数组, 或作为double
数组的数组。
double[N][M]
表示"矩形"形状的 2D 数组,而 double**
允许您通过为矩阵的每一行分配不同数量的内存来构建"自由格式"(交错)数组。
与编译器的不同之处在于,给定double[N][M]
和一对整数{r,c}
它可以通过计算数组原点的偏移量来计算元素的位置,而无需从内存中读取任何内容。但是,给定一个double**
,编译器必须计算指向行的指针的地址,读取该指针,然后才计算目标元素的地址。由于这种差异,两者不可互换。
没有类型 [][]
。您实际上拥有的是 m2
它是一个大小为 4 的数组数组,类型为 double,m1
是一个大小为 1 的数组数组。大小为 4 的数组数组不等同于双指针。
我希望我不会在这里变得愚蠢,但是当您寻址连续内存块时,也会使用符号double [][]
,而double**
不一定是连续的。
我认为这就是错误背后的原因。尽管您可以使用相同的语义来访问值,但它们实际上是不同的类型。
[][] 不等同于 **; double ** var;
是一个指针的指针,正如您在内存中的分配中看到的那样,您持有一个指针数组,其中的每个指针都指向一个 double
值数组
double var [4][4];
保存在内存中,有点等同于双*;在这种情况下,知道矩阵的大小(4 x 4),所以当你使用var[2][2]
时,例如,它知道它在内存中的位置; var[x][y]
翻译为这样的东西:var[x + y * 4]
和声明可以解释为double var [16];
拉克斯万。
No... 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]
会中断:它会以错误的数量前进:指向双精度的指针的大小。
但这还不是全部。还有一个更微妙的错误。如果两个维度都衰减,编译器就无法知道正在访问数组。它会很乐意将pm1b[1]
解释为指向双精度的指针。然后会发生什么?它将获取存储在该位置的任何double
值,并将其视为指向double
的指针。
你可以看到为什么这将是一场灾难。
不,不是。 double[n][m]
为二维数组分配足够大的单个内存块。然后,您可以方便地不必计算自己的索引。将二维数组传递给函数时,编译器要求您提供内部维度的大小,以便它可以计算出索引。
double**
是指向指针的指针。由于 C 允许指针算术,因此它可能意味着一个指针数组,其中每个指针指向一个双精度数组。值本身不需要驻留在连续的内存块中。 如您所见,它们是完全不同的野兽。
如果您有double[n][m]
并希望将其传递给double **
则需要构造自己的索引数组。
另一个区别是,如果您将其声明为 double[][](类似于 final 字段),则不能使 double 指向任何其他内存地址 )
但是,如果您将其声明为 **double,那么它可以指向任何内存位置。
不,它们绝对不等效,前者表示双精度的 2D 数组,而后者表示指向双精度指针的指针。
- 为什么 std::round(sin(pi/6)) 不等于 1?
- 在C++中,为什么int可以使用new运算符初始化变量,而double不能
- 调用的对象类型 'double' 不是 report() 函数的函数或函数指针
- 你怎么编码,如果x不等于一个数字,程序就会退出
- u张量模型输出不等于预期输出
- 虽然不等于陈述和/或差异
- 这种关系不等于定义良好的表达式吗?
- OpenGL 版本不等于支持的着色器版本
- 两个 4 位位字段加起来不等于一个字节的大小 - 如何修复?
- 如果整数不等于 0,则将其减小为 1
- C 循环虽然不等于任何两个值
- vb.net单不等于c float
- 如何获取C编译器#Error如果大小(struct ..)不等于给定的数字
- C++ 而语句不等于检查
- 重载的函数调用double不明确
- 有没有办法检查int是否不等于数组中的所有值?(C )
- 整数数组中的元素数量不等于其大小
- 获取不等于特定值的向量的第一个N元素
- 对 std::原子<double>不加到非原子对应物
- double[][] 不等于 **double?