function composition, sequence point, and unsuspected side effects

K

Keith Thompson

88888 Dihedral said:
Do you push so often in the C program stack for such trivial things?

Finally, something that might *vaguely* be responsive to what I
was asking. Are you saying you're concerned about the expense
of pushing values onto the stack to pass them to the function,
and then returning a struct value (presumably also on the stack)?

If you're interested in having an actual discussion, it would have
beeen helpful if you'd stated your rationale when you first made
the remark -- or at least after being asked.

The C standard says nothing about a "stack". It's true that the
vast majority of C implementations do use an in-memory contiguous
stack. But if the expense of the MakePair() function is such a
concern, you can always inline it (making it conditional on the
__STDC_VERSION__ if you're concerned about older implementations)
and ask your compiler to optimize it.

I don't think I'd bother unless actual measurements showed that it
was a significant problem.

And it's very common for parameters and function return values to
be passed in registers. In this case, the structure is just twice
the size of an int.

Do you often resort to macros for such trivial things?

Incidentally, in this particular case C99's compound literals make the
function largely unecessary -- though not all compilers support them.
The caller is responsible to allocate the structure either in the heap
or the program stack in my version of C programs.

Yes. So what is the advantage of pushing that responsibility onto
the caller? It makes the code more difficult to read and write,
for vanishingly little benefit.

[...]
 
8

88888 Dihedral

Sure, why not?









Why? As you said, it's a trivial thing. Do you also require the

caller to do allocation for long doubles? Maybe just plain old doubles?



You made a comment about "portability", but the more you talk about this,

the less it seems to me like you have a broad experience with different

architectures and how they do or don't handle this.



-s

--

Copyright 2013, all wrongs reversed. Peter Seebach / (e-mail address removed)

http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures

Autism Speaks does not speak for me. http://autisticadvocacy.org/

I am not speaking for my employer, although they do rent some of my opinions.

First the actions of the caller that calls a normal C function with variables are different from
the actions of the use of a macro.

The simple and fast way is better.

Because there's no GC in C,
and in manny embedded systems a small C compiler like LCC or PCC could be embedded but not a big one like
GCC for C and C++.
 
K

Keith Thompson

88888 Dihedral said:
First the actions of the caller that calls a normal C function with
variables are different from the actions of the use of a macro.

Not necessarily. In this case, the behaviors are identical; the
operations performed by the abstract machine may differ, but we don't
run abstract machines.
The simple and fast way is better.

And the question is, which way is simpler?
Because there's no GC in C,
and in manny embedded systems a small C compiler like LCC or PCC could
be embedded but not a big one like GCC for C and C++.

Garbage collection is not required in this case.

Here's a concrete example:

#include <stdio.h>

typedef struct {
int first;
int second;
} Pair;

static Pair MakePair(int first, int second) {
Pair result;
result.first = first;
result.second = second;
return result;
}

#define MAKE_PAIR(p, first_, second_) \
( (p).first = (first_), \
(p).second = (second_) )

int main(void) {
Pair p;
#ifdef MACRO
puts("MACRO enabled");
MAKE_PAIR(p, 100, 200);
#else
puts("MACRO disabled");
p = MakePair(100, 200);
#endif
printf("p = {%d, %d}\n", p.first, p.second);
}

When I compile and generate assembly listings with:
gcc -O3 -S c.c
vs.
gcc -DMACRO -O3 -S c.c
the assembly listings are *identical* except for the message
"MACRO enabled" vs. "MACRO disabled".

Write clear code, and let the compiler worry about performance.

Well, that's not entirely true. Choosing a good algorithm in
particular can help performance significantly, and *sometimes*
tweaking low-level code can be helpful (if actual measurements have
indicated a significant problem, and if you're better at it in some
particular case than the compiler is).

But at least in this particular case, with the particular compiler and
options I used, using your macro vs. a function returning a struct made
exactly no difference in performance.
 
S

Seebs

First the actions of the caller that calls a normal C function with variables are different from
the actions of the use of a macro.

So what? The function is *correct*. The macro often isn't.
The simple and fast way is better.

Except that it can often introduce bugs, because it's not really
simpler.
Because there's no GC in C,
and in manny embedded systems a small C compiler like LCC or PCC could be embedded but not a big one like
GCC for C and C++.

If you're targeting a small embedded system, you cross-compile.

-s
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top