简体   繁体   English

如何返回带有数组的C结构?

[英]How are C structs with arrays returned?

Suppose we have: 假设我们有:

typedef struct {
    uint8_t someVal;
} Entry

typedef struct {
    Entry grid[3][3];
} Matrix

//Make a 3x3 matrix of all 0s
Matrix emptyMatrix(void) {
    Entry zero = {.value = 0}
    Matrix matrix;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++) {
            //Shallow copy empty struct
            matrix.grid[i][j] = zero;
        }
    return matrix;
}

Matrix myMatrix = emptyMatrix();

I understand that in C we're allowed to return a struct from a function so this works and I've tested it. 我理解在C中我们可以从函数返回一个结构 ,所以这个工作,我测试了它。 However, it's unclear to me HOW the assignment works. 但是,我不清楚作业如何工作。

Does the compiler allocate the memory for myMatrix then copy each Entry element of the array in the Matrix struct returned by emptyMatrix() ? 编译器是否为myMatrix分配内存,然后复制emptyMatrix()返回的Matrix结构中数组的每个Entry元素?

I guess it would also be helpful to know the memory map of Matrix - I assumed that since grid is an array that Matrix 's memory would contain pointers. 我想知道Matrix的内存映射也会有所帮助 - 我假设因为grid是一个Matrix的内存包含指针的数组。 However, it apparently stores the value . 但是,它显然存储了价值 If this is the case, my guess for how the assignment works makes much more sense to me. 如果是这种情况,我对作业如何运作的猜测对我来说更有意义。

Edit: It seems like people are answering the question incompletely. 编辑:似乎人们没有完全回答这个问题。 I want to know whether my guess of how the assignment works is correct. 我想知道我对分配工作原理的猜测是否正确。

Each instance of Matrix will contain a 3x3 array of Entry . Matrix每个实例都包含一个3x3的Entry 数组 When you assign one instance of Matrix to another, the contents of the source matrix will be copied to the destination matrix. 将一个Matrix实例分配给另一个实例时,源矩阵的内容将被复制到目标矩阵。

Arrays are not pointers. 数组不是指针。 Array expressions will "decay" to pointers if the expression is not the operand of the sizeof or unary & operators, or is not a string literal used to initialize a character array in a declaration. 如果表达式不是sizeof或一元&运算符的操作数,或者不是用于初始化声明中的字符数组的字符串文字,则数组表达式将“衰减”为指针。

For example, if you had a function call like 例如,如果你有一个函数调用

printMatrix( myMatrix.grid );

the expression myMatrix.grid has type "3-element array of 3-element array of Entry "; 表达 myMatrix.grid具有类型“的3元素数组的3元素数组Entry ”; since it's not the operand of the sizeof or unary & operator, it "decays" to an expression of type "pointer to 3-element array of Entry " ( Entry (*)[3] ) and the value of the expression is the address of the first element of grid (which will also be the address of the whole Matrix instance). 因为它不是的操作数sizeof或一元&运算符,它“衰变”到类型的“指针的3元素数组表达Entry ”( Entry (*)[3]和表达式的值是地址grid的第一个元素(也将是整个Matrix实例的地址)。

The ABI for each environment defines how structures are passed and returned by value. 每个环境的ABI定义了如何通过值传递和返回结构。 A common choice is this: 一个常见的选择是:

  • small structures, up to the size of 2 or 4 registers are returned in registers. 寄存器中返回最小为2或4个寄存器的小结构。

  • for larger objects, the caller allocates space on its stack frame for the return value and passes a pointer to the function. 对于较大的对象,调用者在其堆栈帧上为返回值分配空间,并将指针传递给该函数。 When returning, the function copies whatever object is being returned into the space to which it received a pointer for the return value. 返回时,该函数会将返回的任何对象复制到它收到返回值指针的空间中。 That's it. 而已。 This simple method allows for recursive calls. 这种简单的方法允许递归调用。

  • the optimizer tries to minimize the amount of copying, especially if it can expand the function inline or if the returned value is stored into an object, as opposed to discarded or passed by value to another function. 优化器尝试最小化复制量,特别是如果它可以内联函数或者返回值存储到对象中,而不是丢弃或通过值传递给另一个函数。

It does not matter if the structure has one or more member arrays. 如果结构具有一个或多个成员数组,则无关紧要。 The same method applies to unions as well. 同样的方法也适用于工会。

Identifiers bound to arrays may be interpreted as pointers, but that doesn't mean that the array variables are pointers. 绑定到数组的标识符可能会被解释为指针,但这并不意味着数组变量是指针。

The storage for the array is part of the memory layout of the struct itself. 数组的存储是结构本身的内存布局的一部分。 The same way as arrays declared on the stack are on the stack itself. 与堆栈上声明的数组相同的方式是堆栈本身。

You can test this by yourself by checking sizeof(Matrix) . 您可以通过检查sizeof(Matrix)

So in short: 简而言之:

Does the compiler allocate the memory for myMatrix then copy each Entry element of the array in the Matrix struct returned by emptyMatrix()? 编译器是否为myMatrix分配内存,然后复制emptyMatrix()返回的Matrix结构中数组的每个Entry元素?

Yes

Matrix is a data type struct struct {Entry grid[3][3];} . Matrix是一种数据类型struct struct {Entry grid[3][3];} For every object of the type Metrix memory of size Entry grid[3][3] will be allocated. 对于尺寸为Entry grid[3][3] Metrix存储器类型的每个对象将被分配。
Function emptyMatrix is returning an object of type Matrix and the object will be returned by value just like any other object. 函数emptyMatrix返回一个Matrix类型的对象,该对象将像任何其他对象一样按值返回。

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

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