简体   繁体   English

ANSI C在创建结构时是否必须使用malloc()?

[英]ANSI C do you have to use malloc() when creating a struct?

Let's say I have this struct in ANSI C: 假设我在ANSI C中有这个struct

typedef struct _point
{
    float x;
    float y;
} Point;

and this function to create this struct : 这个函数来创建这个struct

Point createpoint(float x, float y)
{
    Point p;
    p.x = x;
    p.y = y;
    return p; 
}

This allows me to create a struct with this function ie: 这允许我用这个函数创建一个struct ,即:

int main()
{
    Point pointOne = createpoint(5, 6);  
    Point pointTwo = createpoint(10, 4);
    float distance = calculatedistancefunc(pointOne, pointTwo);

    /* ...other stuff */

    return 0;
}

Someone told me that this code is not valid, because the struct does not get malloc 'd in the createpoint(float x, float y) function before it gets returned, and that the struct will be deleted. 有人告诉我这段代码无效,因为struct在返回之前没有在createpoint(float x, float y)函数中获得malloc ,并且struct将被删除。 However, when I use my struct like this, it doesn't seem to get deleted. 但是,当我像这样使用我的struct ,它似乎没有被删除。

So my question is: do I have to malloc this struct , and why? 所以我的问题是:我是否需要malloc这个struct ,为什么? / why not? / 为什么不?

Whatever you are doing is entirely correct. 无论你做什么都是完全正确的。 The statement - 该声明 -

return p;

in the function returns a copy of the local variable p . 在函数中返回局部变量p副本 But if you want the same object that was created in the function, then you need to malloc it. 但是如果你想要在函数中创建的同一个对象,那么你需要malloc它。 However, you need to free it later. 但是,您需要稍后free它。

Point createpoint(float x, float y)
{
    Point p;
    p.x = x;
    p.y = y;
    return p; 
} // p is no longer valid from this point. So, what you are returning is a copy of it.

But - 但是 -

Point* createpoint(float x, float y)
{
    Point *p = malloc(sizeof(Point));
    p->x = x;
    p->y = y;
    return p; 
}// Now you return the object that p is pointing to.

You can return struct on the stack, your code is valid. 您可以在堆栈上返回struct ,您的代码是有效的。 A problem would occur if you'd to return a pointer to the local variable, but that's not what you're doing, you're returning a copy, that's fine. 如果你要返回一个指向局部变量的指针会出现问题,但这不是你正在做的事情,你正在返回一个副本,没关系。

C99 allows for even nicer on-the-stack creation of structs. C99允许更好的堆栈创建结构。
Given the below struct 鉴于以下结构

typedef struct
{
    float x;
    float y;
} Point;

you can initialize it in a bit of a C++ constructor style manner with the following statement: 您可以使用以下语句以一些C ++构造函数样式方式初始化它:

Point p = (Point){0.4, 0.5};

and thus you could either shorten your createpoint or scrap it altogether: 因此,您可以缩短创建点或完全废弃它:

int main()
{
    Point pointOne = (Point){5, 6};
    Point pointTwo = (Point){10, 4};
    float distance = calculatedistancefunc(pointOne, pointTwo);
    //...other stuff
    return 0;
}
Point createpoint(float x, float y)
{
    Point p;
    p.x = x;
    p.y = y;
    return p; 
} /

All local variables in function are deleted after function returns. 函数返回after ,函数中的所有局部变量都将被删除。

1> pass by reference So if you are returning pointer to this local variable then after function return this variables are deleted so that pointers are invalid. 1> 按引用传递因此,如果要返回指向此局部变量的指针,则在函数返回后,将删除此变量,以使指针无效。

2> pass by value But here you are returning copy of this local variable so its safe because that local variable are gona dead when function returns but the copy of return value will be stored in receiver variable in function call before function return. 2> 传递值但是这里你返回的是这个局部变量的副本,所以它的安全性是因为当函数返回时局部变量是死的,但是返回值的副本将在函数返回之前存储在函数调用的接收器变量中。

A call to a method which returns a structure will behave as though the caller creates a temporary variable of the structure type somewhere which isn't visible in any other scope, and gives the called function a pointer to it. 对返回结构的方法的调用将表现得好像调用者在某个地方创建一个在任何其他范围内不可见的结构类型的临时变量,并为被调用函数提供指向它的指针。 The called function will then put the data in the requested place, and after it returns the caller will be able to read the data from its new variable. 然后被调用的函数将数据放在请求的位置,并在它返回后,调用者将能够从其新变量中读取数据。 Given a function and calling code: 给定一个函数和调用代码:

StructType BuildStruct(void)
{
  StructType it;
  it.this=4;
  it.that=23;
  return it;
}

StructType myStruct;
myStruct = BuildStruct();

it's likely that there will be at least one copy operation if not two; 如果不是两个,可能至少会有一个复制操作; the statement return it; 声明return it; may need to copy from local variable it to the temporary struct, and the assignment to myStruct may need to copy from the temporary location to myStruct . 可能需要从本地变量拷贝it到临时结构,并分配给myStruct可能需要从临时位置复制myStruct No situation actually requires two copy operations; 没有情况实际上需要两个复制操作; some require one (which could be performed by the caller or by the called method) and some require none, but the necessity of copying is dependent upon details in both the caller and the called method. 有些需要一个(可以由调用者或被调用的方法执行),有些则不需要,但复制的必要性取决于调用者和被调用方法的细节。

An alternative design would be: 另一种设计是:

void BuildStruct(StructType *it)
{
  it->this=4;
  it->that=23;
}

StructType myStruct;
BuildStruct(&myStruct);

That would likely yield code equivalent to the best code one could hope for using a structure-type return variable, since the struct data would be placed directly into its final spot without any structure copying being necessary. 这可能会产生相当于使用结构类型返回变量的最佳代码的代码,因为struct数据将直接放入其最终位置,而不需要任何结构复制。

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

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