数组C++:你能解释一下这行代码在做什么吗?
arrays in C++: can you explain what this line of code is doing?
我需要修改一些C++代码,但由于我对这门语言相对较新,所以我很难理解一些表达式。
我有一个功能
void func(double m[2][12],double n[2][3])
从像这样的其他函数内部调用
double A[12];
double B[6];
(...)
func( (double (*)[12])A, (double (*)[3])B )
最后一行代码是将 1D 数组转换为 2D 数组,但那里到底发生了什么?我可以使用相同的技术将一维数组转换为二维数组吗,像这样?
double A[12];
double B[6];
(double (*)[12])A[0][5] = 5;
正在发生的事情正是您提到的 - 调用者正在将一维数组转换为 为了将它们传递给 func()
,它有两个指向 2D 数组的指针参数。 由于 C 中的 2D 数组只是"数组的数组"(即不涉及指针(,因此这种转换当然是可能的。 例如,这个一维数组:
int oneDimensionalArray[] = { 0, 1, 2, 3 };
和这个 2D 数组:
int twoDimensionalArray[] = { { 0, 1 },
{ 2, 3 } };
具有完全相同的内存布局。 您可以通过使用疯狂的城镇转换操作来强制类型进行匹配,就像您问题中的操作一样。
至于你的第二个问题,是的,你可以这样做,但你需要另外一组括号:
((double (*)[12])A)[0][5] = 5;
不过,我不建议在编写这种疯狂的事情的代码时。 该计划从何而来?
转换不是从 1D 到 2D 数组,而是指向静态 1D 数组的指针!
double m1[12];
表示类型为">12 个双精度的静态数组"的变量 M1
double m2[2][12];
表示隐式推断类型">2 个元素的静态数组"类型为"12 双精度静态数组"的变量 M2当静态数组用作函数参数时,它们将退化为数组元素类型的指针。因此,对于数组 m1,上面我们可以使用以下任何函数
f11(double arg[12]) {}
f12(double * arg) {}
两者都可以使用任何指向 double 的指针或任何双精度元素数组来调用,例如:
double a=0.0;
double b[10];
f11(&a); f11(b);
f12(&b); f12(b);
类似地,对于数组 m2(上图(,单个元素的类型是"double[12]"。因此,我们可以使用以下任何函数:
f21(double arg[2][12]) {}
f22(double * arg[12]) {}
可以使用指向"12 个双精度数组"的任何指针或任何类型为">12 个双精度数组"的元素数组调用,例如:
double c[12];
double d[6][12];
f21((double (*)[12])c); f21(d);
f22((double (*)[12])c); f22(d);
现在对于您的代码,该函数实际上void func(double m[2][12],double n[2][3])
需要一个指向">12 个双精度的静态数组"的指针和一个指向">3 个双精度的静态数组"的指针。因此,您看到的呼叫
double A[12];
double B[6];
func( (double (*)[12])A, (double (*)[3])B )
实际上将 A(退化为指针到双精度(转换为指向"12 个双精度的静态数组"的指针,并将 B(也退化为指针到双精度(转换为指向">3 个双精度的静态数组"的指针由于所有给定的数组都使用双精度数组,并且静态数组在内存中按顺序表示,因此此类转换可能不会导致逻辑错误。
声明
void func(double m[2][12],double n[2][3])
相当于
void func(double (*m)[12],double (*n)[3])
即第一个数组维度无关紧要。顶级数组类型衰减为指针类型,从而将 2D 数组参数声明转换为指向 1D 数组参数声明的指针。
可以使用这些参数调用此函数
double A[12];
double B[3]; /* note 3 instead of 6 */
正确的方法很简单
func(&A, &B);
请注意,不需要强制转换,只需应用&
运算符,因为A
和B
具有正确的类型(本例中为 double[12]
和 double[3]
(。在这种情况下,在函数内部,人们只能访问m[0][i]
和n[0][i]
,而不能访问m[1][i]
或n[1][i]
,因为它们不存在。
在您的示例中,代码的作者采取了一些非常奇怪的步骤。
首先,显然作者没有意识到第一个参数可以表示为&A
,不需要强制转换,因为A
是用正确的类型声明的。
其次,完全不清楚为什么B
被声明为大小6
数组,当函数需要大小为3
的数组时。为了将此参数强制到该函数中,确实需要显式强制转换。
两个参数的传递方式只是错误代码的一个示例。
至于将一维数组转换为二维数组...请记住,在 C 和 C++ 中,任何 T
类型的对象都可以解释为具有 1 个类型 T
元素的一维数组。只需要将&
运算符应用于对象。例如
int i = 0;
(&i)[0] = 5; /* access `&i` as `int[1]` array */
assert(i == 5);
如果所讨论的对象本身是一个数组,也可以做同样的事情。例如,可以将 1D 数组作为第一个大小等于 1 的 2D 数组进行访问
int a[10] = { 0 };
(&a)[0][8] = 42; /* access `&a` as an `int[1][10]` array */
assert(a[8] == 42);
这正是您的示例中发生的情况,只是正确的方法是将 &
运算符应用于原始对象。代码的作者使用强制转换实现相同的效果。演员不是正确的方法。它不能保证有效,它只是碰巧在实践中具有相同的效果。
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 0-1背包代码中的错误.我的代码中有什么错误
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 这行代码在C++类中意味着什么
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 我可以做些什么来消除或最小化这种将提供相同功能和行为的代码重复
- 以下 C++ 代码用于 -> "#define idiv(a, b) (((a) + (b) / 2) / (b))" 是什么?
- 这个带有模板<类 Vector 的C++代码片段有什么问题>
- 此代码中的操作流程是什么?C/C++.
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- 此代码验证公式是什么意思?
- 需要以下代码的帮助,下面的代码有什么问题
- C++标准提案代码:什么是 N 和 P?
- C - 哈希算法代码什么都没有返回
- 将"12345678"转换为"1-234-5678",我的代码什么也没产生
- 在编译过程中,琐碎的(没有效果的)代码什么时候会被删除
- 有人能告诉我为什么这个代码什么都不打印吗