我如何在C中通过引用传递结构体数组?
以下是一个例子:
struct Coordinate {
int X;
int Y;
};
SomeMethod(Coordinate *Coordinates[]){
//Do Something with the array
}
int main(){
Coordinate Coordinates[10];
SomeMethod(&Coordinates);
}
我如何在C中通过引用传递结构体数组?
以下是一个例子:
struct Coordinate {
int X;
int Y;
};
SomeMethod(Coordinate *Coordinates[]){
//Do Something with the array
}
int main(){
Coordinate Coordinates[10];
SomeMethod(&Coordinates);
}
在C语言中,数组传递的是第一个元素的指针。它们是唯一一个不会真正按值传递的元素(指针是按值传递的,但数组并未复制)。这使得被调用的函数能够修改其内容。
void reset( int *array, int size) {
memset(array,0,size * sizeof(*array));
}
int main()
{
int array[10];
reset( array, 10 ); // sets all elements to 0
}
如果你想改变数组本身(元素数量等),你无法使用栈或全局数组,只能使用在堆中动态分配的内存。在这种情况下,如果你想改变指针,你必须传递一个指向它的指针。
void resize( int **p, int size ) {
free( *p );
*p = malloc( size * sizeof(int) );
}
int main() {
int *p = malloc( 10 * sizeof(int) );
resize( &p, 20 );
}
在问题编辑中,你特别询问了如何传递结构体数组。你有两个解决方案:声明一个typedef或明确说明你正在传递结构体:
struct Coordinate {
int x;
int y;
};
void f( struct Coordinate coordinates[], int size );
typedef struct Coordinate Coordinate; // generate a type alias 'Coordinate' that is equivalent to struct Coordinate
void g( Coordinate coordinates[], int size ); // uses typedef'ed Coordinate
你可以在声明类型时使用 typedef(这是 C 语言中常见的用法):
typedef struct Coordinate {
int x;
int y;
} Coordinate;
稍微解释一下这里的一些答案...
在C语言中,当一个数组标识符出现在除 & 或 sizeof 之外的上下文中时,标识符的类型会隐式转换为“T类型的指针”,并且它的值会隐式设置为数组中第一个元素的地址(与数组本身的地址相同)。这就是为什么当你只将数组标识符作为参数传递给函数时,函数接收到的是基本类型的指针,而不是数组。由于你无法仅通过查看第一个元素的指针来确定数组的大小,因此你必须将大小作为单独的参数传递。
struct Coordinate { int x; int y; };
void SomeMethod(struct Coordinate *coordinates, size_t numCoordinates)
{
...
coordinates[i].x = ...;
coordinates[i].y = ...;
...
}
int main (void)
{
struct Coordinate coordinates[10];
...
SomeMethod (coordinates, sizeof coordinates / sizeof *coordinates);
...
}
有几种传递数组给函数的替代方法。
有一种指向 T 类型数组的指针,与指向 T 的指针不同。你可以这样声明这样的指针:
T (*p)[N];
struct Coordinate { int x; int y };
void SomeMethod(struct Coordinate (*coordinates)[10])
{
...
(*coordinates)[i].x = ...;
(*coordinates)[i].y = ...;
...
}
int main(void)
{
struct Coordinate coordinates[10];
...
SomeMethod(&coordinates);
...
}
struct Coordinate { int x; int y; };
struct CoordinateWrapper { struct Coordinate coordinates[10]; };
void SomeMethod(struct CoordinateWrapper wrapper)
{
...
wrapper.coordinates[i].x = ...;
wrapper.coordinates[i].y = ...;
...
}
int main(void)
{
struct CoordinateWrapper wrapper;
...
SomeMethod(wrapper);
...
}
wrapper
是按值传递的。大约 80 字节,而 SomeMethod()
中的赋值对于在 main
中声明的 wrapper
没有影响。看起来像是一个 bug。 - bobbogoC语言不支持任何类型的按引用传递。最接近的等效方法是传递该类型的指针。
以下是两种语言中的一个人为示例:
C++风格API
void UpdateValue(int& i) {
i = 42;
}
最接近的C语言等效代码
void UpdateValue(int *i) {
*i = 42;
}
请注意,如果您在方法内创建数组,则无法返回它。如果您返回指向它的指针,在函数返回时,它将从堆栈中移除。 您必须在堆上分配内存并返回指向该内存的指针。 例如:
//this is bad
char* getname()
{
char name[100];
return name;
}
//this is better
char* getname()
{
char *name = malloc(100);
return name;
//remember to free(name)
}
默认情况下,数组是通过引用传递的。实际上是传递了指向第一个元素的指针的值。因此,接收到它的函数或方法可以修改数组中的值。
void SomeMethod(Coordinate Coordinates[]){Coordinates[0].x++;};
int main(){
Coordinate tenCoordinates[10];
tenCoordinates[0].x=0;
SomeMethod(tenCoordinates[]);
SomeMethod(&tenCoordinates[0]);
if(0==tenCoordinates[0].x - 2;){
exit(0);
}
exit(-1);
}
void doSomething(MyStruct* mystruct, size_t numElements)
{
for (size_t i = 0; i < numElements; ++i)
{
MyStruct current = mystruct[i];
handleElement(current);
}
}
在C语言中,使用指针是最接近以引用方式调用的方法。
大家好,这是一个简单的测试程序,展示了如何使用new或malloc来分配和传递数组。只需复制,粘贴并运行即可。玩得开心!
struct Coordinate
{
int x,y;
};
void resize( int **p, int size )
{
free( *p );
*p = (int*) malloc( size * sizeof(int) );
}
void resizeCoord( struct Coordinate **p, int size )
{
free( *p );
*p = (Coordinate*) malloc( size * sizeof(Coordinate) );
}
void resizeCoordWithNew( struct Coordinate **p, int size )
{
delete [] *p;
*p = (struct Coordinate*) new struct Coordinate[size];
}
void SomeMethod(Coordinate Coordinates[])
{
Coordinates[0].x++;
Coordinates[0].y = 6;
}
void SomeOtherMethod(Coordinate Coordinates[], int size)
{
for (int i=0; i<size; i++)
{
Coordinates[i].x = i;
Coordinates[i].y = i*2;
}
}
int main()
{
//static array
Coordinate tenCoordinates[10];
tenCoordinates[0].x=0;
SomeMethod(tenCoordinates);
SomeMethod(&(tenCoordinates[0]));
if(tenCoordinates[0].x - 2 == 0)
{
printf("test1 coord change successful\n");
}
else
{
printf("test1 coord change unsuccessful\n");
}
//dynamic int
int *p = (int*) malloc( 10 * sizeof(int) );
resize( &p, 20 );
//dynamic struct with malloc
int myresize = 20;
int initSize = 10;
struct Coordinate *pcoord = (struct Coordinate*) malloc (initSize * sizeof(struct Coordinate));
resizeCoord(&pcoord, myresize);
SomeOtherMethod(pcoord, myresize);
bool pass = true;
for (int i=0; i<myresize; i++)
{
if (! ((pcoord[i].x == i) && (pcoord[i].y == i*2)))
{
printf("Error dynamic Coord struct [%d] failed with (%d,%d)\n",i,pcoord[i].x,pcoord[i].y);
pass = false;
}
}
if (pass)
{
printf("test2 coords for dynamic struct allocated with malloc worked correctly\n");
}
//dynamic struct with new
myresize = 20;
initSize = 10;
struct Coordinate *pcoord2 = (struct Coordinate*) new struct Coordinate[initSize];
resizeCoordWithNew(&pcoord2, myresize);
SomeOtherMethod(pcoord2, myresize);
pass = true;
for (int i=0; i<myresize; i++)
{
if (! ((pcoord2[i].x == i) && (pcoord2[i].y == i*2)))
{
printf("Error dynamic Coord struct [%d] failed with (%d,%d)\n",i,pcoord2[i].x,pcoord2[i].y);
pass = false;
}
}
if (pass)
{
printf("test3 coords for dynamic struct with new worked correctly\n");
}
return 0;
}
memset
作为它应该使用的方式:memset(array,0,size * sizeof *array)
-- 这种情况下sizeof(array)
是指针的大小,而不是所指向的数据大小。 - David Rodríguez - dribeas