Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > struct by value

Reply
Thread Tools

struct by value

 
 
Jon
Guest
Posts: n/a
 
      10-14-2010
Nobody wrote:
> On Wed, 13 Oct 2010 10:04:55 -0700, ImpalerCore wrote:
>
>> First of all, what is the performance implications of using struct
>> pass-by-value for smallish structs?

>
> It depends upon the platform.


That answer is lame. C is defficient and it's defficiencies must not be
glossed over... where is wikipedia when you need her!


 
Reply With Quote
 
 
 
 
Jon
Guest
Posts: n/a
 
      10-14-2010
Project China Blue Book wrote:
> In article
> <(E-Mail Removed)>,
> ImpalerCore <(E-Mail Removed)> wrote:
>
>> When creating an API for a struct in C, one of the questions that
>> recently came up is how to pass that struct or return a struct from a
>> function. Often the answer is obvious, to use pointers, particularly
>> for large structs for performance reasons.

>
> Any value too large to be returned in registers is returned in
> memory;


Oh yeah, confuse all future readers by introducing yet another concept. C
IS a stack-based "language".

> you can deal with this yourself or let the compiler do it.


Yes, C is ambiguous.

> Concentrate instead on what makes the most sense for your interface.


Oh, you teaching? Someone you don't even know from Joe. Stop that!

>
> Historically only scalars could be returned because the returned
> value had to fit in a register. That restriction has been removed,
> but old interfaces live forever and with it the reluctance for
> returning structs.


Write a f!@n paper! (Or you new-fangled guys call that "Dr. Dobbs
Online"). (It was just a book chapter anyway).


 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      10-14-2010
On 10/14/2010 12:24 AM, Jon wrote:
> Eric Sosman wrote:
>>> The struct pass-by-value version of the interface avoids the pesky
>>> NULL pointer argument issue, but still I can't get away from it
>>> completely since I use 'int (*compare_function)( const void* p, const
>>> void* q )' to define the sorting property in my generic containers.

>>
>> Sorry; I can't make sense of this. If "the pesky ... issue" is
>> that a struct pointer might be NULL, well, that can often be a help
>> rather than a harm: You can provide a NULL for an "optional" struct
>> pointer argument, but you cannot do so with a struct value.

>
> Much more often than not, "the pesky issue" is the case at hand.
> Asserting for null pointers is a PITA and an unnecessary one. Potential
> language-level solutions: references that can't be null, a "not null" or
> "can be null" keyword.


It seems that you and the O.P. somehow regard null pointer values
as Bad Things, poison pills in your program. That's an attitude I can't
understand, as it seems important to be able to respond to "Get another
Thing" with "No Thing there, boss." The null-valued pointer is a very
convenient device, a way to pass either "Here's a Thing" or "No Thing"
through one channel, without the burden of inventing a separate channel
for an independent "Yes/No" answer (with "No" also having the meaning
of "Just pay no attention to that Thing in the other channel; it's not
really there").

A pointer type that cannot be null seems to me crippled, about as
useful as a numeric type that cannot be zero. A pointer that is known
to be non-null when I'm about to use it (or a number known to be non-
zero when I'm about to divide by it) is useful, but that's not the same
thing, not the same thing at all.

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      10-14-2010
On 10/14/2010 2:03 AM, Jon wrote:
> Nobody wrote:
>> On Wed, 13 Oct 2010 10:04:55 -0700, ImpalerCore wrote:
>>
>>> First of all, what is the performance implications of using struct
>>> pass-by-value for smallish structs?

>>
>> It depends upon the platform.

>
> That answer is lame. C is defficient and it's defficiencies must not be
> glossed over... where is wikipedia when you need her!


Oh, come on! Show me a language that *prescribes* the run-time
cost of its operations -- or even the relative cost -- and I'll show
you a language with far more defficiencies [sic] than C.

--
Eric Sosman
(E-Mail Removed)lid
 
Reply With Quote
 
ImpalerCore
Guest
Posts: n/a
 
      10-14-2010
On Oct 13, 9:32*pm, Eric Sosman <(E-Mail Removed)> wrote:
> On 10/13/2010 1:04 PM, ImpalerCore wrote:
>
>
>
> > When creating an API for a struct in C, one of the questions that
> > recently came up is how to pass that struct or return a struct from a
> > function. *Often the answer is obvious, to use pointers, particularly
> > for large structs for performance reasons.

>
> > However, as the struct size shrinks, the choice of passing struct by
> > value or by pointer becomes less clear to me. *Let me use a simple
> > struct as an example.

>
> > struct greg_ymd
> > {
> > * *int16_t year;
> > * *int8_t month;
> > * *int8_t day;
> > };

>
> > I use this struct to represent a date in the gregorian calendar
> > (fields not offset to start from 0). *Let's say that I want to have a
> > function that adds a certain number of days to this ymd struct. *There
> > are a couple of options that come to mind.

>
> > 1. *struct greg_ymd add_days( const struct greg_ymd ymd, int days );

>
> * * *What does `const' buy you? *Or, why not `const int days'? *Other
> than that, this seems plausible.


The only thing I can think of is it may prevent some logical error in
a bad implementation of add_days. Provided the implementation of
add_days is sound, there isn't anything 'const' buys you that I can
think of.

> > 2.<return type> *add_days( struct greg_ymd* pymd, int days );

>
> * * *This seems plausible, too.
>
> > First of all, what is the performance implications of using struct
> > pass-by-value for smallish structs?

>
> * * *Mu.
>
> > Is there a rule of thumb of struct size for an interface API that you
> > convert all struct parameter passing to use pointers?

>
> * * *When writing software that others might blame you for, the basic
> rule of thumb is "Leave no fingerprints." *
>
> > Have you used struct by value parameter passing or return value at all
> > in your API design experience?

>
> * * *Yes. *For parameters, I'd estimate that I use a struct pointer
> more frequently than a struct value, maybe 90%-10% or even more
> lopsided. *For function values, leaving "lookup-ish" functions aside,
> I'd guess my own ratio is closer to 70%-30%. *YMMV.
>
> > The struct pass-by-value version of the interface avoids the pesky
> > NULL pointer argument issue, but still I can't get away from it
> > completely since I use 'int (*compare_function)( const void* p, const
> > void* q )' *to define the sorting property in my generic containers.

>
> * * *Sorry; I can't make sense of this. *If "the pesky ... issue" is
> that a struct pointer might be NULL, well, that can often be a help
> rather than a harm: You can provide a NULL for an "optional" struct
> pointer argument, but you cannot do so with a struct value. *As for
> your comparison function, the relevance escapes me: You've already
> chosen to pass pointers, so what are you asking about?


I personally don't have any problem with using or passing NULL
pointers myself. Unfortunately, that is not how everyone views it.

Let's watch an episode of the NULL pointer blame game.

Me: I got this new little library that does something cool.
I want you guys to try it out.
Develop: Yeah, it works pretty well, except that it crashes when
I pass a NULL pointer to the interface.
Me: So, don't pass NULL pointers, NULL pointers are not
intended to be semantically viable, like strcpy and friends,
so why should I complicate my interface to handle something
that developers should know better anyways. It's in the
documentation.
Manager: But that's the standard library and we don't have control
over that. We do have control over your library API, so why
not make it a little more robust to developer mistakes.
Testing resources can't cover everything, so why should we
make more opportunities to crash the application if we don't
have to.
Me: Invest in more testing then. We deal with strcpy issues
because we have to ... oorrrrr maybe we can just add asserts
to help the developers.
Tester: I don't like the assert idea. I don't want to have to test
two versions of the software, with and without assert.
Me: Okay, so if I make NULL pointer not crash, how do you want
to communicate the error, by return value?
Develop: Sounds fine.
Me: <grumbles>

.... sometime later ...

Tester: We found some funny side effects from that new library your
using. It looks like there could be a problem.
Develop: Interesting, nothing came up in our tests. We'll ask the
library guy.
Me: Hey Developers, what's up?
Develop: The tester found some strange behavior from using your
library.
Me: Ok. What's the problem?
Develop: We're not sure, but since you're the expert on the way your
library works, we'd like your help to troubleshoot it.
Me: Fine. ... <looks at developer code and notices that there
are no error checks from using library function> ... I
noticed that you're not checking for errors from the API.
Could a NULL pointer be causing an issue?
Develop: Could be.
Me: hmmm ... thinking ... <If it's a NULL pointer again, I
should just let the NULL pointer crash their code, then at
least they know it was their fault, but management says
that they don't have resources for complete and perfect
testing, so make your library robust. I wonder how
passing struct by value would change things.>

Best regards,
John D.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-14-2010
"Jon" <(E-Mail Removed)> writes:
> Keith Thompson wrote:

[...]
>> I'd say that "small" structs can sensibly be passed by value (unless
>> of course the function needs to modify them), and "large" structs
>> should be passed by pointer for performance reasons.
>>
>> I have no particular guidance to offer about the dividing line between
>> "small" and "large". I'd say that anything no larger than a pointer
>> is certainly "small", but beyond that ...
>>
>> I know that's not very helpful.

>
> How about this "rule": if it's a primitive, pass by value, else don't.
> There are not stack frame guarantees that allow further portable
> ("overall") rules of thumb, as far as I know.


What exactly do you mean by "primitive"?

If you mean that scalar types (i.e., numeric and pointer types)
should be passed by value and other types (arrays, structs, unions)
should be passed by pointer, well, that's a consistent rule, but it
fails to take advantage of C's ability to pass and return structs
and unions by value.

If you have a small struct type, I see no reason not to pass it
by value if that satisfies the semantics you need.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-14-2010
"Jon" <(E-Mail Removed)> writes:
[...]
> References are nice in that regard, but I have a feeling it is not
> guaranteed portable (sorry for the C++ chat).

[...]

References are perfectly portable in C++. They don't exist in C
(which you'll notice is the language we discuss here).

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-14-2010
"Jon" <(E-Mail Removed)> writes:
> Gene wrote:

[...]
>> I have done some tests in the past with 32-bit gcc and Visual C. Both
>> would move structs to registers for call-by-value params, local
>> assignment (as in swapping struct values) and return values if the
>> size was 4 bytes or less.

>
> OK, then, here is something I don't understand: if those compilers do
> that, how am I supposed to write an assembly language prologue/epilogue
> to interface such things if arguments are not passed on the stack?


The same way you would in any circumstances: by understanding the
calling convention used by the compiler, which is probably based
on the ABI for the platform.

But how often do you need to write an assembly language
prologue/epilogue anyway?

[...]

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-14-2010
"Jon" <(E-Mail Removed)> writes:
> Nobody wrote:
>> On Wed, 13 Oct 2010 10:04:55 -0700, ImpalerCore wrote:
>>
>>> First of all, what is the performance implications of using struct
>>> pass-by-value for smallish structs?

>>
>> It depends upon the platform.

>
> That answer is lame. C is defficient and it's defficiencies must not be
> glossed over... where is wikipedia when you need her!


That answer is correct, and I see nothing lame about it.

Are you suggesting that the performance implications should be
defined by the language? How exactly would that work?

The purpose of a C program is not to generate CPU instructions.
CPU instructions are a tool used to create the run-time behavior
that the C program specifies; that behavior is what the program is
all about. (There are cases where you care which instructions are
generated, but such cases are, and should be, rare.)

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-14-2010
"Jon" <(E-Mail Removed)> writes:
> Project China Blue Book wrote:
>> In article
>> <(E-Mail Removed)>,
>> ImpalerCore <(E-Mail Removed)> wrote:
>>
>>> When creating an API for a struct in C, one of the questions that
>>> recently came up is how to pass that struct or return a struct from a
>>> function. Often the answer is obvious, to use pointers, particularly
>>> for large structs for performance reasons.

>>
>> Any value too large to be returned in registers is returned in
>> memory;

>
> Oh yeah, confuse all future readers by introducing yet another concept. C
> IS a stack-based "language".


(Why did you put the word "language" in quotation marks?)

You seem to be new here, so you may not be aware that we've
discussed this at great and tedious length before.

No, C is not a stack-based language. The word "stack" doesn't even
appear in the C language standard. The semantics of C function calls
do imply some kind of stack-like structure, but only in the sense
that storage for function calls is allocated and deallocated in a
last-in first-out manner. There is no implication of a stack laid
out in contiguous memory growing and shrinking in any consistent
direction.

Having said that, most C implementations *do* use a contiguous
stack in memory -- but not all do. There are implementations
where the storage for each function call is allocated on the heap.
The assumption of a contiguous stack is neither universally correct
nor particularly useful. And even in stack-based implementations,
it's very common to pass some arguments in registers.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can *common* struct-members of 2 different struct-types, that are thesame for the first common members, be accessed via pointer cast to either struct-type? John Reye C Programming 28 05-08-2012 12:24 AM
Typedef A references struct B which references struct A which... DanielEKFA C++ 8 05-16-2005 10:26 AM
struct in struct Gunnar G C++ 14 06-02-2004 06:43 PM
struct my_struct *p = (struct my_struct *)malloc(sizeof(struct my_struct)); Chris Fogelklou C Programming 36 04-20-2004 08:27 AM
implementing a templated struct within a templated struct RA Scheltema C++ 3 01-06-2004 11:25 AM



Advertisments