From: Jonathan Kirwan
Subject: Re: To C or not to C
References: <firstname.lastname@example.org> <email@example.com> <firstname.lastname@example.org> <email@example.com>
X-Newsreader: Forte Agent 1.92/32.572
NNTP-Posting-Date: Sun, 05 Jan 2003 06:17:52 GMT
Organization: AT&T Broadband
Date: Sun, 05 Jan 2003 06:17:53 GMT
On Sun, 5 Jan 2003 01:42:26 +0100, "Frank Bemelman"
>"Jonathan Kirwan" schreef in bericht
>> On Sun, 5 Jan 2003 01:35:19 +0100, "Frank Bemelman"
>> >"Jonathan Kirwan" schreef in bericht
>> >> I wasn't thinking about that. C can simulate "rotate left" and
>> >> "rotate right," for example, or bit set and bit clear, as you
>> >> mention. I'm talking about <> which simply cannot be
>> >> reached. I'm not talking 'just clumsily', but *impossible* no
>> >> matter how much or little code is written. Quite another story.
>> >Yes, but a rather short story. There isn't much desire to
>> >manipulate stackpointers etc. in the middle of an (application)
>> Not what I'm thinking of. I'll provide a nice and *actual*
>> example of one of my case histories which occured only a year
>> ago for me, after some more guessing goes on. But it will be an
>> "oh, yeah" after you see it.
>Okay, I'll keep scratching my head in the meantime ;)
Hehe, okay. I'll list a few which might trigger more. It's not
even close to a complete list, but it does poke a few holes to
suggest other ideas.
Link-time constants. It's possible in most assembly languages
to specify external symbols and assign a value to those symbols.
Not the storage for them. The symbols themselves. COBOL
compilers, using VALUE IS EXTERNAL for example, can reference
these. C can, as well, with &symbol where 'symbol' is an
extern. But if you want to create them, in C, you cannot.
The advantage I've taken with them on larger projects is that I
could avoid recompiling all the .C files which refer to, say, a
#define symbol. Instead, I'd simply compile the configuration
parameter .C file once and the symbol values would then be
available in the .O or .OBJ file. The linker would then paste
in the appropriate values at link time, based on these.
For example, rather than:
#define MAXBUF (128)
in a .H file, I might instead use:
const MAXBUF = 128;
in a .C configuration file which I could then compile into an
.OBJ or .O. The linker would have access to this symbolic value
and would link it appropriately with any extern references to
it, substituting the values at link time.
Without this mechanism, the C compiler must recompile each and
every .C file which includes the .H, rather than recompiling
only the configuration constants file and then linking. For
large projects, this can be kind of nice.
But there are other values to this. For example, being able to
specify absolute addresses for memory mapped peripheral
registers and so on. Some of the embedded C compilers actually
provide pre-compiled .OBJ or .O files which include these
predefined symbolics in them for convenience and provide
appropriate .H files for inclusion. But it isn't possible to
produce those .OBJ files (or .LIB) without the assembler being
involved. C just doesn't have a syntax to specify the semantics
Generating equal times in the 'then' and 'else' clauses of an
'if'. I recently encountered a situation, in doing bus
arbitration between a variable number of asynchronous devices
sharing it, where the timing of each address bit during the
arbitration phase (much like the APIC bus on the Intel P II
cpus) depended on some constant factors PLUS two times the
variability in the bit timing. Since this was an active low,
high impedance high type of line sharing, the microcontroller
had to use two different mechanisms for driving a '0' and a '1'.
This meant that I couldn't just mask the bit and drive it to the
latch. I had to use an 'if' statement and do different things
depending on whether the bit was a 0 or 1. However, if the
'then' and 'else' clauses had different timing, I'd have to
double that variability and add it into the total bit time and
this could greatly slow down the resolution process.
C simply doesn't provide a syntax to allow the programmer to
specify to the compiler that this is a desired outcome. Not
even nice #pragma's for this, for example. No amount of
screwing around with the C code would help here. It's plain and
simple, not in the C card deck.
Co-routines. It would take a while to properly elaborate this
one. A quick example in pig-C might get the point across more
for (p in Primes (1, 100))
for (n in Treewalk (t))
In either of these cases, the function is called with the
specified parameter list and doesn't quite "return" but instead
"yields" a value back. The stack context for Primes() or
Treewalk() must be maintained so that any local variables and
the function parameters are maintained throughout the for loop.
But when the function yields a value, the loop continues once,
and then returns back from the yield. In effect, this is a
coroutine -- cooperative, simple to implement, and powerful. In
the case of the Primes() call, for example, the full set of
primes do not need to be passed back nor fully computed before a
yield takes place. There is no equivalent in C. But this is
actually quite easy in assembly (and some other higher level
Those are just three very real cases. There are also special
uses of the ALU status bits which allow math and logical
operations to be vastly more efficient, for some algorithms,
than C. But now we are getting back onto the speed issue and
I'm trying to point out that there are other issues. So I'll
just note that detail.
Assembly is quite a bit more flexible than C. The difficulty is
that one needs to have a broader set of mental models in order
to take advantage of that flexibility.
There are also some more 'technical' differences, of course.
Like interrupt procedures. C doesn't provide a syntax for this.
Of course, many compiler vendors *do* provide extensions, so
that it's not impossible for a C programmer -- such as a #pragma
or a special keyword. So perhaps this is more a technicality.
Or the ability to specifically place variables with initialized
constant values in flash or rom. But many compilers now
automatically detect this or provide some syntax to specify it.
So perhaps another technicality here.
Anyway, I just wanted to point out that those limiting their C
vs assembly arguments to "speed" or "space", being unable to see
any other reasons, are in fact myopic and color blind in their
views. There is a bigger, more colorful world out there, most
especially in embedded work. And C vs assembly for embedded use
doesn't just boil down to speed and space and development time.
I admit it often does so, but not always. And it's the times
when it doesn't boil down that way, that things are really more