On 12/05/15 05:42, Tim Rentsch wrote:
> David Brown <
david...@hesbynett.no> writes:
>
<snip>
> The cost I'm talking about is a coding and maintenance cost,
> not a compilation or performance cost. I don't mind agreeing to
> the possibility that your sense of the size of that cost may be
> different from mine.
Fair enough. I don't think we need a discussion about the differences
in such costs in this context - at least, not in this thread.
>>
>> The point of this thread was to ask people with different
>> experiences and styles if they could think of an advantage of the
>> way strcat is defined - precisely because while I could not think
>> of one myself, I thought that someone else might. So far no one
>> (including you) has given any suggestions other than "it seemed a
>> good idea at the time" or "they standardised the function they
>> were using, without thinking about other use-cases". [snip]
>
> My answer may not have been stated very clearly, but I did
> suggest another possible explanation, namely, for reasons you
> don't consider important, namely coding convenience in certain
> situations, those making the choice thought, and still think (or
> would think, if they were still alive), that this consideration
> outweighs those of the alternate semantics, even after conscious
> evaluation.
>
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?
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?
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.
// Combine three strings and return the total length
int combineStrings(char* s, const char* t1, const char* t2) {
strcat(s, t1); // Time len(s) + len(t1)
strcat(s, t2); // Time len(s) + len(t1) + len(t2)
return strlen(s); // Time len(s) + len(t1) + len(t2)
}
// Total time 3*len(s) + 3*len(t1) + 2*len(t2)
int combineStrings(char* s, const char* t1, const char* t2) {
char* end = strcat2(s, t1); // Time len(s) + len(t1)
end = strcat(end, t2); // Time len(t2)
return end - s; // Time 1
}
// Total time len(s) + len(t1) + len(t2) + 1
(Note that if you really don't like the extra "char* end" variable, you
can use strcat2 exactly like strcat in the first version.)
It is also simpler and more efficient to implement strcat in terms of
strcat2 rather than the reverse:
char * strcat(char* s, const char* t) {
strcat2(s, t); // Time len(s) + len(t)
return s;
}
// Total time len(s) + len(t)
char * strcat2(char* s, const char* t) {
strcat(s, t); // Time len(s) + len(t)
return strlen(s); // Time len(s) + len(t)
}
// Total time 2*len(s) + 2*len(t)
So it is clear that there are common cases where a strcat2 returning the
end pointer is more flexible and significantly more efficient than the
standard version. There are no cases in which the standard version is
more efficient. And the standard version is easily and efficiently
created from the strcat2 version.
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.