C: Return value via stack/register question

别来无恙 提交于 2019-11-28 21:26:06

The way that the return value is passed to the caller is part of the function calling conventions as well. See here.

For example, regarding cdecl:

The cdecl calling convention is used by many C systems for the x86 architecture. In cdecl, function parameters are pushed on the stack in a right-to-left order. Function return values are returned in the EAX register (except for floating point values, which are returned in the x87 register ST0).

[...]

There are some variations in the interpretation of cdecl, particularly in how to return values. As a result, x86 programs compiled for different operating system platforms and/or by different compilers can be incompatible, even if they both use the cdecl convention and do not call out to the underlying environment. Some compilers return simple data structures with the length of 2 registers or less in EAX:EDX, and larger structures and class objects requiring special treatment by the exception handler (e.g., a defined constructor, destructor, or assignment) are returned in memory. To pass "in memory", the caller allocates memory and passes a pointer to it as a hidden first parameter; the callee populates the memory and returns the pointer, popping the hidden pointer when returning.

The stack manipulations are going to be much much faster than the heap manipulations necessary if you allocate memory on the heap, so stack is always faster. The only reason (in C) you might want to return a pointer to something on the heap is because it won't fit on the stack.

Clarification:

In the last sentence above, "the only reason you might want..." should not be interpreted as "there is normally no reason to return a pointer". Rather, I mean "if you can do what you need without returning a pointer, the only reason to decide to use a pointer anyway is...".

Of course there are many valid reasons to return pointers from functions as Chris states in his own answer, but I 'm only talking about the cases where you don't need to do so.

In other words, return by value when you can; use pointers when you must.

And one more: would it be right to say that objects I want to return, larger than register should be stored in heap and returned by pointer to prevent all than stack manipulations?

Well, maybe. Honestly, the choice of "return by pointer" or "return by value" is one you should probably have better reasons to make than "I want the return to be faster." For example, it would be faster to return via pointer than via stack for large objects, but this isn't taking into account the greater amount of time it takes to allocate an object on the heap compared to the stack.

More importantly, return-by-pointer allows you to have opaque pointers, variably-sized objects and certain degrees of polymorphic behavior that are impossible in stack objects. If you want or need these kinds of behaviors, you should be using return-by-pointer anyway. If you don't, you can use return-by-value, or you can pass a pointer to an object allocated by the user (however they like) as a parameter and modify that parameter in your function (this is sometimes called an "out parameter" or something similar).

Choose the return method based on what you need and what your code does, not which you think is faster. If you find that you absolutely need the speed (after profiling and finding that the return is a bottleneck), then worry about this kind of micro-optimization.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!