S
Seebs
If a, b, and c are of some built-in type, then `a = b + c;` cannot
involve any function calls in either C or C++.
Sure it can. It could involve a call to a function called __addquad().
-s
If a, b, and c are of some built-in type, then `a = b + c;` cannot
involve any function calls in either C or C++.
Seebs said:Sure it can. It could involve a call to a function called __addquad().
Sure it can. It could involve a call to a function called __addquad().
... For that matter, the addition or one
of the conversions could, on some systems, require an implicit function
call. ...
My point is that C cannot reasonably be described as any kind of
assembly language. Do you actually disagree with that statement?
No. My position is that C is exceedingly mechanical ... so much so that
there is nearly a 1:1 ratio between the things it does and the things the
CPU must do to conduct the workload.
... That closeness is known to all who
know C and assembly. The fact that other C developers may not know it as
a matter of stored knowledge is immaterial because the relationship exists
fundamentally. ...
Rick C. Hodgin said:No. My position is that C is exceedingly mechanical ... so much so that
there is nearly a 1:1 ratio between the things it does and the things the
CPU must do to conduct the workload. That closeness is known to all who
know C and assembly. The fact that other C developers may not know it as
a matter of stored knowledge is immaterial because the relationship exists
fundamentally.
David Brown said:<snip snivelling drivel>
Rick C. Hodgin said:No. My position is that C is exceedingly mechanical ... so much so that
there is nearly a 1:1 ratio between the things it does and the things the
CPU must do to conduct the workload. That closeness is known to all who
know C and assembly. The fact that other C developers may not know it as
a matter of stored knowledge is immaterial because the relationship exists
fundamentally.
Do you ignore optimization?
No.
A compiler can, for example, generate no code at all for a given
statement, or for an entire function, if it can prove that that
statement or function has no effect.
[snip]
I care about the behavior of the running program. Machine or
assembly language is nothing more or less than a means to that end.
Agreed.
(If I cared for some reason about the existence of an ADD instruction in
the generated code, then I'd use assembly language.)
The term ratio really implies numbers; in the only senses I can figure
out for which numbers might apply, 1:1 is clearly false.
One of the more common events in this newsgroup is someone posting a
message complaining about the fact that he can't figure out how to make
a C compiler generate assembly language that matches that person's
opinion of how the assembler should be written. This complaint is based
upon the same mistaken 1-to-1 assumption that you're making. Such people
should either abandon that assumption, or write in assembler; the C
standard, as a matter of deliberate design goes far out of it's way to
make sure that the correspondence does NOT have to be 1-to-1.
The fact that some people mistakenly assume a 1-to-1 correspondence is
immaterial to the fact that, as a matter of very deliberate design, it
is not actually required to be 1-to-1, and usually isn't.
Rick C. Hodgin said:Rick C. Hodgin said:No. My position is that C is exceedingly mechanical ... so much so that
there is nearly a 1:1 ratio between the things it does and the things the
CPU must do to conduct the workload. That closeness is known to all who
know C and assembly. The fact that other C developers may not know it as
a matter of stored knowledge is immaterial because the relationship exists
fundamentally.
Do you ignore optimization?
No.
A compiler can, for example, generate no code at all for a given
statement, or for an entire function, if it can prove that that
statement or function has no effect.
[snip]
I care about the behavior of the running program. Machine or
assembly language is nothing more or less than a means to that end.
Agreed.
(If I cared for some reason about the existence of an ADD instruction in
the generated code, then I'd use assembly language.)
Agreed.
So you've completely reversed your position?
The term ratio really implies numbers; in the only senses I can figure
out for which numbers might apply, 1:1 is clearly false.
I said "nearly a 1:1 ratio between the things it does and the things the
CPU must do to conduct the workload."
int main(void)
{
int a, b;
populate_my_variables(&a, &b);
printf("The product is: %d\n", a, b);
return 0;
}
; Off the top of my head, please forgive any mistakes:
; // int main(void)
; // {
; // int a, b
enter 8,0
; [ebp-0] - a
; [ebp-4] - b
; // populate_my_variables(&a, &b);
; // [implicit return][populate_my_variables][address_of a][address_of b]
push ebp ; [address_of b]
mov eax,ebp ; [address_of b];
sub eax,4
push eax
call populate_my_variables ; [populate_my_variables]
add esp,8 ; [implicit return]
; // printf("The product is: %d\n", a, b);
; // [printf]["The..\n"][a]
push dword ptr [ebp-4] ;
push dword ptr [ebp-0] ; [a]
push address_of "The product is: %d\n" ; ["The..\n"]
call printf ; [printf]
add esp,12
; // return 0
mov eax,0
; // }
leave
ret
In this case, there are 14 separate things that must be considered
for conversion:
[1]int [2]main([3]void)
{
int [4]a, [5]b;
[6]populate_my_variables([7]&a, [8]&b);
[9]printf([10]"The product is: %d\n", [11]a, [12]b);
[13]return [14]0;
}
These are translated to 15 separate things done in assembly (including
function overhead), and this in wholly un-optimized mode.
; Off the top of my head, please forgive any mistakes:
; // int main(void)
; // {
; // int a, b
01: enter 8,0
; [ebp-0] - a
; [ebp-4] - b
; // populate_my_variables(&a, &b);
; // [implicit return][populate_my_variables][address_of a][address_of b]
02: push ebp ; [address_of b]
03: mov eax,ebp ; [address_of b];
04: sub eax,4
05: push eax
06: call populate_my_variables ; [populate_my_variables]
07: add esp,8 ; [implicit return]
; // printf("The product is: %d\n", a, b);
; // [printf]["The..\n"][a]
08: push dword ptr [ebp-4] ;
09: push dword ptr [ebp-0] ; [a]
10: push address_of "The product is: %d\n" ; ["The..\n"]
11: call printf ; [printf]
12: add esp,12
; // return 0
13: mov eax,0
; // }
14: leave
15: ret
My compiler actually does things notably differently so I never have to
pass more than one parameter (which is register passed). But, that's
a whole separate discussion.
On 01/29/2014 04:57 PM, Rick C. Hodgin wrote:
Well, it's the optimized mode that's really most relevant, and this code
is far to simple to allow significant opportunities for optimization.
You'll have to provide a platform-dependent definition of how to count
the number of things that a given piece of C code must do, in order to
make your comment meaningful.
If you do, I guarantee that whatever
definition you choose, it will be trivial to identify some combination
of source code, platform, compiler, and compiler options for which the
ratio is NOT 1:1. In fact, it will be far easier to identify such
combinations than to identify ones for which it is 1:1.
It's feasible, in code this simple, to take each line of assembly code
and associate it with a unique part of the original source code. If you
call those the "things" that the C code must do, then of course the
numbers will match.
But different compilers will produce different sets
of assembly language instructions when targeting different platforms,
and when different optimizations are turned on. Those can't all be in a
1-to-1 relationship to the same "thing" count;
which renders your claim
that there must be such a relationship nonsense. I've seen the same C
code converted into 10 assembly language instructions by one compiler,
and 500 instructions by another.
Both sets of "things" to do were fully
consistent with the requirements of the C standard. Which number
constituted the correct count of the "things" that the C code was
supposed to do?
Note that some of the relevant optimizations take things
like a+b*c and convert then into a single floating point instruction
that takes three arguments.
On the flip side, on a platform where there is no > native support for
floating point or for any data type larger than 32 bits, a simple
statement a=b, which does a maximum of three "things" as far as C is
concerned, can involve a MUCH large list of assembly language if a and b
have the types "long long" and "long double complex", respectively.
Actually, the fact that your compiler does something different is the
norm, not the exception, which is precisely what is being discussed.
No. My position is that C is exceedingly mechanical ... so much so that
there is nearly a 1:1 ratio between the things it does and the things the
CPU must do to conduct the workload. That closeness is known to all who
know C and assembly.
Optimized code is nearly always shorter than un-optimized code.
In general, everything that has a name definition, has an operator, is
separated by a comma, is part of an assignment, or is part of a logic test.
I don't think this is a universal view of C. C is derived (as I
may have said before ) from BCPL, and one of the stated aims
of BCPL was to eliminate hidden overheads. I believe C was also
intended to follow this philosphy. So users can expect their
code to do no more than what they have written, and this may
well be one of the reasons why they are using C in the first place.
Not really. If the computation isn't horribly expensive,
you can run through 2**32 examples in a few minutes.
2**64 would likely be intractable, though.
James Kuyper said:The term ratio really implies numbers; in the only senses I can figure
out for which numbers might apply, 1:1 is clearly false. For instance,
the number of lines of assembler is almost completely unrelated to the
number of lines of C code. It can be quite a bit larger or smaller,
depending upon what the C code actually says.
I assume that what you really mean is "correspondence", rather than
"ratio". For some simple low-level languages, it it possible to set up a
1-to-1 correspondence between language constructs and the generated
assembly code. However, such a language is really nothing more than a
high-level assembler.
C is not, and never has been, such a language,
though the correspondence was closer in the early days of C than it is
now.
There are a million ways you can bring it unique conditions which destroy
my argument. It doesn't change the merit of it on the whole.
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.