我一直被告知使用指向原始数组的指针并将其传递进去。
有人告诉您使用指向原始数组元素的指针。您被告知这是因为如果您尝试声明一个按值获取数组的函数,该语言会指定参数类型已“调整”以获取指向元素类型的指针(有效地导致数组参数类型忘记其大小并通过引用而不是按值传递)。所以基本上你被告知手动进行调整,以便源代码准确而明确地代表实际情况。
您显示的声明也可以使用以下建议声明:
static void SceneMeshInitIndices(GLushort *meshIndices);
static void SceneMeshUpdateNormals(SceneMeshVertex (*mesh)[NUM_MESH_ROWS]);
static void SceneMeshUpdateMeshWithDefaultPositions(SceneMeshVertex (*mesh)[NUM_MESH_ROWS]);
应该清楚的是,一种类型的int [X][Y]
意思是“一个由 Y 个整数组成的 X 数组的数组”。所以元素类型是“一个 Y 整数数组”。因此调整后的类型是“int (*)[Y]”或“指向 Y 个整数数组的指针”。
“调整”参数类型的规则是原始数组糟糕的几个原因之一,如果可以避免它们,则不应使用它们。不幸的是,C 并没有真正的好方法来做到这一点,但是 C++ 有std::array
,它的行为就像数组一样;即您可以按值传递它们,可以按值返回它们,它们不会自动转换为指向元素类型的指针(因此它们永远不会忘记它们的大小)等。
也许更多的例子会更清楚。如果你写:
void foo(int param[10]);
而且您不知道调整参数类型的规则,那么您可能会期望以下代码会产生错误:
int bar[5];
foo(bar); // error? an array of 5 ints is not the expected type.
对于这段代码:
int baz[10];
foo(baz);
您可能希望将数组bar
复制到参数中,并且对参数所做的任何修改都不会影响原始数组。不幸的是,这些完全合理的期望是错误的。当您编写时void foo(int param[10]);
,编译器会看到具有数组类型的参数并将其修改为与您编写的相同void foo(int *param);
因此,当您编写foo(bar)
编译器时,编译器会看到该函数采用 an int*
(不是int[10]
您编写的那个),看到它可以转换bar
为 an int *
,因此编译器不会报告错误,而是恶意地生成一个调用该函数的程序。无论您编写的类型与传递的变量不兼容,无论其主体foo()
可以做类似的事情param[9] *= 2;
并且应该确保这是明确定义的。
同样,foo(baz)
不按值传递数组,对函数内部的数组参数所做的任何事情都直接在实际数组上完成。这与通常的 C 语义完全不同,其中所有内容都通过值/副本传递,“通过引用传递”的唯一方法是获取充当对另一个对象的引用的指针值。在这种情况下,编译器会自动为您获取一个指针,并通过引用有效地传递数组。
此外,请注意,您是否写void foo(int [10])
或void foo(int [100])
无关紧要;在这两种情况下,参数类型都被调整为int *
,因此这些声明声明了相同的函数,即使它们看起来不同。