(snip, someone wrote)
>>> Can you give me:
>>> 1. An example where strcat, as defined today, leads to /significantly/
>>> clearer, neater, more maintainable, or more efficient code than a
>>> "strcat2" function that returns a pointer to the end of the string?
An important word above is "today". strcat wasn't designed recently,
and hardware was a lot different when it was. Decisions that are
right today, may not have been right 40 years ago.
>>> 2. A justification why you think such coding style was likely in the
>>> early days of C, thus making it a reasonable explanation for the
>>> choice of strcat?
>> No, I'm not offering either of those. I'm not saying the reasons
>> mentioned are ones you would find convincing, only that is it
>> plausible that the original designers found them convincing.
That was just at the transitions from writing operating systems,
and even compilers, in the appropriate assembly language, possibly
with various aids to make it easier, to writing them in high level
languages. Multics is, as I understand it, mostly PL/I.
C and unix were for smaller computers. It is mostly that we, today,
decided to take what was optimal for small computers and assume it
optimal for large ones.
> I realise that - that's why I asked you for a justification for why you
> think the original designers did it this way. But I am not yet
> convinced that the original designers thought this through properly. I
> can accept that they might have had different balances between
> efficiency and simplicity, or compilers with different abilities, or
> different styles. However, I am still lacking /any/ justification for
> suggesting the original library designers thought "strcat" was a better
> choice than "strcat2". Currently, it appears that they simply didn't
> consider the issues. (And that's fair enough - we can't expect them to
> have had perfect hindsight when starting out. We must simply live with
> it as another of C's sub-optimal design decisions.)
The inefficiency of strcat() is O(n*n). (O(n**2) in some newsgroups.)
(I had to actually debug a program once where someone had used
strcat() in a loop, where actual O(n**2) timing was visible.)
When n=10, you don't notice, and the existing strcat() may be
optimal.
>>> It's very easy to find situations where a strcat2 (returning a pointer
>>> to the end of the string) is clearer and more efficient than strcat.
(snip)
>> These examples don't seem very compelling to me, because what the
>> functions do seems somewhat contrived, and because they don't
>> match how I expect they would be written, especially if
>> efficiency concerns were paramount. (I assume you meant strcat2
>> rather than strcat in the second definition.)
> They are simply example functions that demonstrate the difference
> between strcat and strcat2 when combining several strings. Feel free to
> write them in a more efficient form - once using the standard strcat,
> strcpy, strlen functions, and once using strcat2. No loops to manually
> copy the strings are allowed (because that would be missing the point of
> having the library functions). I am curious to see how you would write
> them with greater efficiency.
In the actual case mentioned above, I used strlen() and strcpy().
Using strlen() allowed me to verify that the new string would fit.
>>> It is also simpler and more efficient to implement strcat in terms of
>>> strcat2 rather than the reverse:
(snip)
>> I might agree on the "more efficient" part, but not on "simpler"
>> part.
In many cases, strcat() or strcat2() aren't good choices.
They work well when you can be reasonably (enough) sure that you
won't outrun the array. If you can't, there are easier ways than
to test first and then strcat().
> You cannot possibly /disagree/ on the "more efficient" part - strcat can
> be implemented optimally from strcat2, while the opposite direction
> requires double the time. (In theory, a smart enough compiler could
> remove the function calls and turn the strcat + strlen into an inlined
> loop.)
As above, I suspect original strcat() was used closer to n=10.
It is nice when you want to add an extension onto a file name.
You might:
x=fopen(strcat(file,".xyz"),"w");
It is not nice when you want to read in megabytes of data, one
screen-width line at a time.
> And how can you justify contending on the "simpler" part? Implementing
> strcat from strcat2 requires one function call, while implementing
> strcat2 from strcat requires two function calls. I won't claim it's a
> complicated function, but there can be no doubts as to which is simpler.
(snip)
>> I understand that you think this reasoning is convincing. Not
>> everyone does.
> I have given a fair amount of justification and evidence for why my
> reasoning makes sense. I still have heard absolutely no technical
> justification for the choice of strcat as we have it today, compared to
> strcat2 (or a version that returned the length of the new string, which
> would be another reasonable alternative). You have done nothing but
> claim that the original library authors might have had good reason for
> the decision.
Your reasoning might make sense today, but maybe not 40 years ago.
I don't know by now, maybe someone does, was the original strcat()
written in C, or the appropriate assembly?
>>> The question is, does the standard version lead to significantly neater
>>> or clearer code in common cases, and was it common enough to lead to a
>>> concious design decision when the library was standardised? Or was it,
>>> as most people here seem to think, a bad decision - probably the result
>>> of standardising someone's existing usage rather than the result of a
>>> thoughtful design.
>> Why do you find it so hard to believe that other people might
>> reasonably reach different conclusions than you do?
If you haven't read K&R1, you should do that. That should give
you a better idea of what the original designers of C expected
it to do. How they thought it might be used.
> I like to base my conclusions on evidence and technical justifications,
> if I can. I can find plenty of evidence for the viewpoint that strcat2
> would have been a better choice for the standard library than strcat. I
> can find no significant evidence to the contrary, and no one else here
> seems to have done so either.
Well, for one, many C library string routines return a pointer to the
first argument. It is nice to have a little consistency.
> The nearest I have seen is the fact that strcat allows certain chained
> expression syntaxes that cannot be written directly with strcat2 - you
> need to use multiple expressions. But even in such cases, the strcat2
> version is not more difficult, and it is much more efficient. And no
> one has argued that such chained expressions were common in old C code,
> or that they were a reason for picking the strcat form.
> So the question is, why do you find it so hard to believe that the
> original design decision was not a good one, and was perhaps made in
> haste or for "historical" reasons?
I suspect that if you asked the original C designers, at the time,
if they expected C to be popular 40 years later, they would have
said "no". Not that they didn't believe in their design, but there
are many people out there with good ideas. Statistically, it wasn't
so likely to happen.
-- glen