将结构数组传递给函数 C++ [英] Passing array of structures to function c++

查看:53
本文介绍了将结构数组传递给函数 C++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起,我有点困惑.
如果我想传递给函数的 main 结构数组:

Sorry for the noob question I'm just a little confused.
If I have an array of structures in main that I want to pass to a function:

struct MyStruct{
    int a;
    int b;
    char c;
    mayarray[5];
};  
MyStruct StructArray[10]; 

myFunction(StructArray[])

传递给一个函数:

void myFunction(struct MyStruct PassedStruct[])
{
    PassedStruct[0].a = 1;
    PassedStruct[0].b = 2;
    // ... etc
}  

我的问题是,像这样调用函数会修改StructArray中的数据吗?我需要它.这会是引用调用吗?我有点困惑.我将如何更改它,以便当我将结构数组传递给函数时,该函数将修改数组 StructArray?顺便说一句,我正在考虑 Visual Studio.
谢谢.

My question is, will calling the function like this modify the data in StructArray? I need it to. Would that be call by reference? I'm a little confused. How would I change it so that when I pass the array of structures to the function, the function will modify the array StructArray? I'musing visual studio btw.
Thanks.

推荐答案

struct MyStruct PassedStruct[]

主要的替代语法:

struct MyStruct * PassedStruct

是的,您将访问和修改原始结构.

So yes, you will access and modify the original structure.

只需更改一个细节,对函数的正确调用不是

Just one detail to change, the correct call to to the function is not

myFunction(StructArray[]);

但是:

myFunction(StructArray);

现在我将尝试解释为什么我在上面的句子中使用主要这个词:

Now I will try to explain why I used the word mostly in the above sentence:

我将给出一些关于数组和指针之间的区别的提示,为什么你不应该混淆它们(即使我不会说它们不相关,恰恰相反),以及上述 MyStruct PassedStruct 的问题[] 参数传递语法.

I will give some hint at the difference between arrays and pointers, why you shouldn't confuse them (even if I would not say they are unrelated, quite the opposite), and the problem with the above MyStruct PassedStruct[] parameter passing syntax.

这不适合初学者,C++ 标准专家也应该避免阅读(因为当我进入 ISO 未定义行为领域时,我不想卷入一些 - ISO Standard_war - aka forbidden领土)​​.

This is not for beginners, and C++ standard experts should also avoid reading this (because I don't want to get in some - ISO Standard_ war as I enter ISO undefined behavior territory - a.k.a. forbidden territory).

让我们从数组开始:

想象一个简单的结构:

struct MyStruct{
    int a;
    int b;
    char c;
};  

MyStruct a1[3]; 是数组的声明,其项为上述结构类型.定义数组时,编译器所做的最重要的事情就是为其分配空间.在我们的示例中,它为 3 个结构保留了空间.这个保留空间可以在堆栈上,也可以来自全局内存资源,具体取决于声明语句的位置.

MyStruct a1[3]; is the declaration of an array whose items are of the above structure type. The most important thing the compiler does when defining an array is to allocate space for it. In our example it reserved space for 3 structs. This reserved space can be on stack or from global memory resources depending where the declaration statement is.

您也可以在声明结构时初始化它,如下所示:

You can also initialize the struct when declaring it like in:

struct MyStruct a1[3] = {{1, 2}, {3, 4}, {5, 6}};

请注意,在此示例中,我没有初始化 c 字段,而只是初始化了 ab.这是允许的.如果我的编译器支持它,我也可以使用指示符语法:

Notice that in this example, I didn't initialize the c field but just a and b. This is allowed. I could also use designator syntax if my compiler supports it like in:

struct MyStruct a1[3] = {{a:1, b:2}, {a:3, b:4}, {a:5, b:6}};

现在,还有另一种使用空方形 backets 定义数组的语法,例如:

Now, there is another syntax for defining an array using empty square backets like in:

struct MyStruct a2[] = {{1, 2}, {3, 4}, {5, 6}};

这里的重点是 a2 是一个完全正常的数组,就像 a1 一样.数组大小不是隐式的,它是通过初始化程序给出的:我有三个初始化程序,因此我得到了一个包含三个结构的数组.

The point here is that a2 is a perfectly normal array just like a1. The array size is not implicit, it is given through the initializer: I have three initializers therefore I get an array of three structs.

我可以用这个语法定义一个已知大小的未初始化数组.对于大小为 3 的未初始化数组,我会:

I could define an uninitialized array of known size with this syntax. For an uninitialized array of size 3 I would have:

struct MyStruct a2[] = {{},{},{}};

分配空间,与前面的语法完全一样,这里不涉及指针.

Space is allocated, exactly as with the previous syntax, no pointer involved here.

我们来介绍一个指针:

MyStruct * p1;

这是一个指向 MyStruct 类型结构的简单指针.我可以通过通常的指针语法 p1->a(*p1).a 访问字段.还有一个数组风格的语法来做与上述 p1[0].a 相同的事情.还是和上面一样.你只需要记住 p1[0] 是 (*(p1+0)) 的简写.

This is a simple pointer to a structure of type MyStruct. I can access fields through usual pointer syntax p1->a or (*p1).a. There is also an array flavored syntax to do the same as above p1[0].a. Still the same as above. You just have to remember that p1[0] is a shorthand for (*(p1+0)).

还要记住指针算法的规则:给一个指针加1意味着把指向的对象的sizeof加到底层内存地址上(当你使用%p printf格式参数时会得到什么).指针算术允许访问连续的相同结构.这意味着您可以使用 p1[0]p1[2] 等通过索引访问结构.

Also remember the rule for pointer arithmetic: adding 1 to a pointer means adding the sizeof the pointed object to the underlying memory address (what you get when you use %p printf format parameter). Pointer arithmetic allows access to successive identical structs. That means that you can access structs by index with p1[0], p1[2], etc.

不检查边界.在内存中指向的是程序员的责任.是的,我知道 ISO 的说法不同,但这是我尝试过的所有编译器所做的,所以如果您知道有一个没有,请告诉我.

Boundaries are not checked. What is pointed to in memory is the programmer's responsibility. Yes, I know ISO says differently, but that is what all compilers I ever tried do, so if you know of one that does not, please tell me.

要对 p1 做任何有用的事情,您必须使其指向某个 MyStruct 类型的结构体.如果你有一个像我们的 a1 这样的结构数组,你可以只做 p1=a1 并且 p1 将指向数组的开头.换句话说,您也可以完成 p1=&a1[0].使用简单的语法是很自然的,因为它正是指针算法的设计目的:访问相似对象的数组.

To do anything useful with p1, you have to make it point to some struct of type MyStruct. If you have an array of such structs available like our a1, you can just do p1=a1 and p1 will point to the beginning of the array. In other words you could also have done p1=&a1[0]. It's natural to have a simple syntax available as it's exactly what pointer arithmetic is designed for: accessing arrays of similar objects.

该约定的美妙之处在于它允许完全统一指针和数组访问语法.只有编译器才能看到差异:

The beauty of that convention is that it allows to completely unify pointer and array access syntax. The difference is only seen by the compiler:

  • 当它看到 p1[0] 时,它知道它必须获取名称为 p1 的变量的内容,并且它将包含地址一些内存结构.

  • when it sees p1[0], it knows it has to fetch the content of a variable whose name is p1 and that it will contain the address of some memory structure.

当它看到 a1[0] 时,它知道 a1 是一个常数,应该被理解为一个地址(不是要在内存中获取的东西).

when it sees a1[0], it knows a1 is some constant that should be understood as an address (not something to fetch in memory).

但是一旦 p1a1 的地址可用,处理是相同的.

But once the address from p1 or a1 is available the treatment is identical.

一个常见的错误是写p1 = &a1.如果你这样做,编译器会给你一些四个字母的单词.好吧,&a1 也是一个指针,但是当你获取 a1 的地址时,你得到的是一个指向整个数组的指针.这意味着如果你给这种类型的指针加 1,实际地址将一次移动 3 个结构.

A common mistake is to write p1 = &a1. If you do so the compiler will give you some four letter words. Ok, &a1 is also a pointer, but what you get when taking the address of a1 is a pointer to the whole array. That means that if you add 1 to a pointer of this type the actual address will move by steps of 3 structures at once.

那种指针的实际类型(我们称之为p2)将是MyStruct (*p2)[3];.现在您可以编写 p2 = &a1.如果要访问 p2 指向的内存块开头的第一个结构 MyStruct,则必须编写类似 p2[0][0] 的内容].a(*p2)[0].a(*(*p2)).a(*p2)->ap2[0]->a.

The actual type of a pointer of that kind (let's call it p2) would be MyStruct (*p2)[3];. Now you can write p2 = &a1. If you want to access the first struct MyStruct at the beginning of the memory block pointed to by p2 you will have to write somethings like p2[0][0].a or (*p2)[0].a or (*(*p2)).a or (*p2)->a or p2[0]->a.

多亏了类型系统和指针算法,所有这些都在做完全相同的事情:获取包含在 p2 中的地址,将该地址用作数组(一个已知的常量地址),如上所述.

Thanks to type system and pointer arithmetic all of these are doing exactly the same thing: fetch the address contained in p2, use that address as an array (a known constant address) as explained above.

现在您可以理解为什么指针和数组是完全不同的类型,不应混淆,正如某些人所说.简单地说,指针是包含地址的变量,数组是常量地址.请不要喷我 C++ Gurus,是的,我知道这不是完整的故事,并且编译器保留了许多其他信息以及地址、指向(寻址?)对象的大小.

Now you can understand why pointers and arrays are totally different types that should not be confused as some may say. In plain words pointers are variable that contains an address, arrays are constant addresses. Please don't shoot me C++ Gurus, yes I know that is not the full story and that compilers keep many other informations along with address, size of pointed (addressed ?) object for example.

现在你可能想知道为什么在参数传递上下文中你可以使用空方括号,它实际上意味着指针.?不知道.有人可能认为它看起来不错.

Now you could wonder why in parameter passing context you can use empty square brackets and it really means pointer. ? No idea. Someone probably thought it looked good.

顺便说一句,至少对于gcc,您还可以在括号之间放置一些值,而不是将它们留空.它不会有什么区别,您仍然会得到一个指针,而不是数组,并且不会进行边界或类型检查.我没有检查 ISO 标准是否应该完成,如果标准要求或者是特定行为.

By the way, at least with gcc, you can also put some value between brackets instead of keeping them empty. It won't make a difference you'll still get a pointer, not an array, and boundaries or type checking are not done. I didn't checked in ISO standard was should be done and if it is required by the standard or if it is a specific behavior.

如果您想对边界进行类型检查,只需使用引用即可.这可能令人惊讶,但这是一个区域,如果您使用引用,则参数的实际类型会从指针更改为数组(而不是像预期的那样从指针到引用更改为指针).

If you want type checking for boundaries, just use a reference. That may be surprising but this is an area where if you use a reference, the actual type of the parameter is changed from pointer to array (and not from pointer to reference to pointer as may be expected).

MyStruct StructArray[10]; 

  • header: void myFunction(struct MyStruct * PassedStruct)
  • 调用者:myFunction(StructArray)
  • 状态:有效,你使用 PassedStruct 中的指针
    • header: void myFunction(struct MyStruct PassedStruct[])
    • 调用者:myFunction(StructArray)
    • 状态:有效,你使用 PassedStruct 中的指针
    • header: void myFunction(struct MyStruct (& PassedStruct)[10])
    • 调用者:myFunction(StructArray)
    • 状态:有效,您使用对大小为 10 的数组的引用
    • header: void myFunction(struct MyStruct (& PassedStruct)[11])
    • 调用者:myFunction(StructArray)
    • 状态:未编译,原型和实际参数之间的数组类型不匹配
    • header: void myFunction(struct MyStruct PassedStruct[10])
    • 调用者:myFunction(StructArray)
    • 状态:有效,PassedStruct 是一个指针,提供的大小被忽略
    • header: void myFunction(struct MyStruct PassedStruct[11])
    • 调用者:myFunction(StructArray)
    • 状态:有效,PassedStruct 是一个指针,提供的大小被忽略

    这篇关于将结构数组传递给函数 C++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆