简体   繁体   English

将结构数组传递给函数

[英]passing structure array to function

I've been learning C for about 2 months, still a novice:(学C大概2个月了,还是菜鸟:(

I know there are other similar questions on this site.我知道这个网站上还有其他类似的问题。 I've read them, but still couldn't really understand, so here I am.我已经阅读了它们,但仍然无法真正理解,所以我在这里。 Below is my code:下面是我的代码:

//naming my structure as ball
typedef struct ball_room {
int enter;
int exit;
} ball;

//I've omitted some irrelevant details for brevity
    int i, n, max;
    scanf("%d", &n);
    ball person[n];
    .../*assign values to ball.enter and ball.exit with user input*/
    max = 1;
    for (i = 0; i < n; i++)
        if (ball_room(person, person[i].enter, n) > max)
            max = ball_room(person, person[i].enter, n);
    printf("%d\n", max);
    return 0;
}

and below is my function receiving the array:下面是我接收数组的函数:

//This function returns the number of people in the ballroom
//when b[j](person[j] in "main") enters
int ball_room(ball *b, int i, int n)
{
    int people = 0, j;
    for (j = 0; j < n; j++)
        if (b[j].enter <= i && b[j].exit > i)
            people++;
    return people;
}

my question is that why is it b[j].enter instead of b[j]->enter , which my compiler wouldn't accept?我的问题是为什么它是b[j].enter而不是b[j]->enter ,我的编译器不会接受? In my limited experience, when manipulating structure itself (the object), I use .以我有限的经验,在操作结构本身(对象)时,我使用. to go inside the structure, and when it's a pointer (the address), I use -> (hope this is correct.)进入结构内部,当它是指针(地址)时,我使用-> (希望这是正确的。)

And in this case, I pass the array to function using ball *b , which represent the address of person[0] , so I can access the whole array.在这种情况下,我使用ball *b将数组传递给函数,它表示person[0]的地址,因此我可以访问整个数组。 But shouldn't ball *b be in the form of a pointer and therefore I should use -> to access its content?但是ball *b不应该是指针的形式,因此我应该使用->来访问它的内容吗? It's just an address that I pass to the function.这只是我传递给函数的一个地址。

This is my first time doing something with an array of structures, please help me get this clear, thank you!这是我第一次对结构数组做一些事情,请帮我弄清楚,谢谢!

Given ball *b , b[j] is an element from the elements that b points to.给定ball *bb[j]b指向的元素中的一个元素。 Thus b[j] is not a pointer;因此b[j]不是指针; it is a struct.它是一个结构。 Since it is a struct, you use .由于它是一个结构,因此您使用. to refer to members in it.引用其中的成员。

The definition of b[j] in the C standard is that it is *((b)+(j)) . C 标准中b[j]的定义是*((b)+(j)) So it takes the pointer b , moves j elements beyond it, and then applies * .所以它需要指针b ,将j元素移到它之外,然后应用*

Since * is already applied in b[j] , you do not need -> , just .由于*已应用于b[j] ,因此您不需要-> ,只需. . .

you use .你用. instead of -> because of this declaration of parameters:而不是->因为这个参数声明:

int ball_room(ball *b, int i, int n)

b is expected to be pointer to data with type ball , so you can access it in various ways: b应该是指向类型为ball数据的指针,因此您可以通过多种方式访问​​它:

  1. array way: eg b[5].somefield = 15 - you use dot here, because if b is of type ball * , it means that b is pointer OR it is array of objects with type b , if it's array of objects with type b (which is your case) you use .数组方式:例如b[5].somefield = 15 - 你在这里使用点,因为如果b是类型ball * ,这意味着b是指针或者它是类型为b的对象数组,如果它是类型为对象的数组b (这是您的情况)您使用. to access fields of object访问对象的字段
  2. pointer way: eg (b+5)->somefield = 15 - it will do exactly same thing as code above, but you will access data in pointer way指针方式:例如(b+5)->somefield = 15 - 它会做与上面代码完全相同的事情,但您将以pointer方式访问数据

In C/C++ an array devolves into the address of it's first member.在 C/C++ 中,数组转化为它的第一个成员的地址。 So when you pass the array to ball_room what actually gets passed is &ball[0] .因此,当您将数组传递给ball_room ,实际传递的是&ball[0]

Now inside ball_room the reverse happens.现在在ball_roomball_room了相反的情况。 b is a pointer to ball. b是一个指向球的指针。 But here you use it as an array b[j] .但是在这里您将它用作数组b[j] So it un-devolves back into an array of structs.因此,它会重新分解为一组结构体。 So what b[j] gives you is the struct and not a pointer to a struct.所以b[j]给你的是结构而不是指向结构的指针。 Consequently you access it using .因此,您可以使用. instead of -> .而不是->

You can also use (b + j)->somefield .您也可以使用(b + j)->somefield Or for even more fun how about writing j[b].somefield .或者更有趣的是如何编写j[b].somefield The later being a really confusing left-over from the eraly compiler days when a[b] truly got turned into *(a + b) internally.后者是早期编译器时代真正令人困惑的遗留物,当时a[b]真正在内部变成了*(a + b)

For explanation of the current issue, see Eric 's answer ;有关当前问题的解释,请参阅Eric回答 in some of the answers given so far there is dangerous wording applied, so just to make clear: When do we have an array and when a pointer???在迄今为止给出的一些答案中,应用了危险的措辞,所以只是要明确:我们什么时候有一个数组,什么时候有一个指针???

Consider the following:考虑以下:

int a[7];

As long as we can refer to a directly, we still have an array and can use any operations that are valid on, eg getting size:只要我们可以直接引用a ,我们仍然有一个数组,可以使用任何有效的操作,例如获取大小:

size_t n = sizeof(a); // size in bytes, not ints, i. e. 7*sizeof(int)

You can pass arrays to functions or even do pointer arithmetics on:您可以将数组传递给函数,甚至可以对以下内容进行指针运算:

f(a);
a + 1;

In both cases, the array "decays" to a pointer, though, and the result is a pointer as well.但是,在这两种情况下,数组都会“衰减”到指针,结果也是指针。 Be aware that you can assign new values to a pointer, but not to an array itself (you can assign new values to the array's elements, directly or via pointer), so you cannot do things like ++a either.请注意,您可以为指针分配新值,但不能为数组本身分配新值(您可以直接或通过指针为数组元素分配新值),因此您也不能执行++a

When an array decays to a pointer, it gets a pointer to its first element:当一个数组衰减到一个指针时,它会得到一个指向它的第一个元素的指针:

int* ptr = a;
int* ptr = &*a;    // only pointers can be dereferenced -> a decays!
int* ptr = &a[0];  // short for &*(a + 0)...

All result in exactly the same;所有结果完全相同; however, the following is invalid:但是,以下内容无效:

int* ptr = &a;

Taking the address of an entire array actually is possible, but the resulting pointer is not of type "pointer to element" nor of type "pointer to pointer to element" ( int** in the example), but of type "pointer to array of specific size".获取整个数组的地址实际上可能的,但结果指针不是“指向元素的指针”类型,也不是“指向元素的指针”类型(示例中的int** ),而是“指向数组的指针”类型具体尺寸”。 Syntax for is ugly, though, but the following would be legal again:不过,for 的语法很难看,但以下内容再次合法:

int(*aptr)[7] = &a;

You need to read: if I dereference ptr , I get int[7] ...你需要阅读:如果我取消引用ptr ,我会得到int[7] ...

Once decayed, there is only a pointer to the array left (more precisely: to one of the array elements, directly after decaying, to the first; array and first element always share the same address, so, although of different type, both pointers ptr and aptr from above hold exactly the same value).一旦衰减,只剩下一个指向数组的指针(更准确地说:指向一个数组元素,在衰减之后直接指向第一个;数组和第一个元素总是共享相同的地址,因此,尽管类型不同,两个指针上面的ptraptr保持完全相同的值)。 Pointers can be moved around within the array, but they do not hold as much information as the array itself, especially, the array size gets lost.指针可以在数组内移动,但它们保存的信息没有数组本身那么多,尤其是数组大小丢失了。 This is why one needs to pass the array's length together with the pointer to functions (if needed; another variant is a sentinel value denoting the array end such as the terminating null character in strings or the null pointer following the string arguments in main 's arguments list):这就是为什么需要将数组的长度与指向函数的指针一起传递(如果需要;另一种变体是表示数组结尾的标记值,例如字符串中的终止空字符或main字符串参数后面的空指针)参数列表):

int a[7];
f(a, sizeof(a)/sizeof(*a)); // division: sizeof is in bytes, dividing by size
                            // of first element gives number of elements

Possibly with f as:可能与 f 为:

void f(int b[], size_t n)
//     ^^^^^^^ in function parameter lists, just alternative syntax for int* b !!!
//             however, we can show more explicitly that we expect a pointer
//             to an array this way...   
{
    size_t m = sizeof(b); // as b is a POINTER, gives the constant (but hardware specific!)
                          // size of a pointer (on typical modern 64-bit hardware 8 bytes),
                          // no matter what size of the array being pointed to is!!!

    while(n)
    {
        *b++ = n--;
    //    ^^ advances pointer, NOT array!
    }
}

Hope this helps to avoid confusion.希望这有助于避免混淆。

In C, the array name is a pointer to array's first element, hence your function declaration has name ball *b and works when you pass a ball[] instance.在 C 中,数组名称是指向数组第一个元素的指针,因此您的函数声明具有名称ball *b并且在您传递ball[]实例时起作用。

Try dynamically allocating the memory by using malloc() and passing that pointer to your function.尝试使用malloc()动态分配内存并将该指针传递给您的函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM