2011-10-05 40 views
14

比方说,我有这个struct在ANSI C:ANSI C在创建结构时是否必须使用malloc()?

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

而这个函数来创建这个struct

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

这让我创建这个功能即struct

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

    /* ...other stuff */ 

    return 0; 
} 

有人告诉我这段代码无效,因为struct没有n在返回之前在createpoint(float x, float y)函数中获得malloc'd,并且struct将被删除。 但是,当我使用我的struct这样,它似乎并没有被删除。

所以我的问题是: 我必须要malloc这个struct,为什么?/为什么不?

回答

13

无论你在做什么都是完全正确的。声明 - 在功能

return p; 

返回复制局部变量p。但是如果你想要在该函数中创建相同的对象,那么你需要malloc它。但是,您以后需要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. 

但是 - 在功能

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. 
+0

这是恕我直言的那种病态建议。如果你想做内存管理的权利,你不应该返回一个指向你的函数分配的dinamically分配结构的指针。您应该在第三个参数中请求预先分配的指针,并将其填充到您的方法中。 – mg30rg

+0

@ mg30rg当你可以在函数中完成并返回它时,为什么要传递一个预先分配的结构指针? – Houssni

+3

@YassineHoussni - 由于您比编写代码更可能会读取您的代码,所以在编写舒适性时代码可读性更重要。如果将内存分配和释放保留在同一个块中,则内存泄漏将变得更加困难,因为资源仅保留在需要的确切时间段,并且每次的清理(即:'malloc()'/'getmem() '/'new')与解除分配('free()'/'freemem()'/'delete')配对。你可以很容易地发现没有delete的'new',但是你会发现'createpoint()'没有'delete'吗?维护程序员会这样做吗? – mg30rg

7

您可以在堆栈上返回struct,您的代码有效。如果你想返回一个指向局部变量的指针,会发生问题,但这不是你正在做的,你正在返回一个副本,没关系。

+2

但是你应该关心内存使用情况,如果你使用更大的结构遵循相同的过程,因为每个字段在返回时都被复制。在那个具体情况下,这不应该是一个问题。 –

+1

@Kernald - 存在内存使用问题,性能问题,堆栈深度问题,但与OP的直接问题无关。它**是一个有效的C代码。 – littleadv

+0

感谢大家的明确答案, 但我似乎无法理解为什么'通过引用'比'传递值'更有效率的内存。我的意思是,这两种方式在结构中存储相同数量的数据? –

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

所有的局部变量都将被删除after函数返回。

1>通过引用传递 所以,如果你正在返回指向此局部变量函数,然后返回后该变量被删除,以便指针是无效的。

2>按值传递 但在这里你是返回这个局部变量的副本,所以它的安全,因为那个局部变量是戈纳死当函数返回,但返回值的副本将被存储在接收器变量函数调用函数返回之前。

+0

感谢您的明确解释,但我现在有一个新的问题。 什么时候你应该喜欢通过参考传递,什么时候你应该通过价值传递? –

+0

当你要malloc在本地函数中的东西,然后通过refference&当你返回的东西局部变量传递它的值..更多你可以谷歌它.. !!! –

+0

你也可以提出另一个问题...! –

5

C99允许更好地在栈上创建结构。
鉴于以下结构

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

您可以用下面的语句有点构造风格方式的C++初始化:

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

,因此你既可以缩短你的createpoint或完全废了:

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

对返回结构的方法的调用将表现得好像调用者创建了struc的临时变量在任何其他范围内都不可见的地方,并为被调用的函数提供一个指向它的指针。然后被调用函数将把数据放在请求的地方,并且在返回之后调用者将能够从其新变量中读取数据。给定一个函数和调用代码:

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

StructType myStruct; 
myStruct = BuildStruct(); 

很可能至少有一个复制操作,如果不是两个;声明return it;可能需要从本地变量it复制到临时结构,并且可能需要将myStruct的分配从临时位置复制到myStruct。实际上并不需要两次复制操作;有些需要一个(可以由调用者或被调用的方法执行),有些不需要,但是复制的必要性取决于调用者和被调用方法的细节。

一种替代设计将是:

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

StructType myStruct; 
BuildStruct(&myStruct); 

这可能会产生码等效于一个可以希望使用结构型返回变量的最佳代码,因为该结构数据将被直接放置到其最终没有任何结构复制是必要的。

相关问题