C (functional programming) VS C++ (object oriented programming)

R

Richard

santosh said:
jacob said:
Richard said:
jacob navia said:
H. is arguing that strncmp is not a string comparison function.
Heathfield
That's right. [snip]

Yes, I agree that it's a comparison function. So what?

OK. I give up.

Are you really saying you don't know the difference between a comparison
function and string comparison function?

The crucial difference between strcmp and strncmp is that the former _needs_
it's arguments to be null-terminated strings while the latter doesn't.
There is a crucial difference between an array of characters, (which
needn't, but could be, a string), and a string.

This is another example of petty one upsmanship and word twisting. Both
work almost exactly the bloody same. The difference is that ONE of them
specifies the maximum number of characters to compare. Not a huge
difference but potentially a very optimal difference where the first N
characters are the UID of the object in question.

Yes, CLEARLY strmp needs a well formed string and strncmp doesnt.

To accuse someone of not knowing the difference between a comparison
function and a "string comparison" function is, in this case, trite and
petty when one considers that its very obvious that the poster knows
what the functions do.
 
R

Richard

jacob navia said:
santosh said:
jacob said:
Richard Heathfield wrote:
jacob navia said:
H. is arguing that strncmp is not a string comparison function.
Heathfield
That's right.
[snip]

Yes, I agree that it's a comparison function. So what?

OK. I give up.

Are you really saying you don't know the difference between a comparison
function and string comparison function?

The crucial difference between strcmp and strncmp is that the former _needs_
it's arguments to be null-terminated strings while the latter doesn't.
There is a crucial difference between an array of characters, (which
needn't, but could be, a string), and a string.

Look:

1) The standard names EXPLICITELY strncmp a "comparison functions" in
the section String handling.
2) strncmp starts with the prefix "str"
3) Contrary to memcmp, strncmp will STOP the comparison at a zero byte,
i.e. it has STRING SEMANTICS!

But you go on telling that it is not a string comparison function. Ask
any programmer:

Santosh: Good Morning Sir. I am Santosh and I am
making a poll about string functions. Just a single
question: "Strncmp is a string comparison function or not"?

and see what answers you get.

This is so ridiculous that I just can't believe it. Heathfield can say
anything here and there will be always people that follow his stuff.

I agree.

From the Linux info page:

"strcmp, strncmp - compare two strings"

Santosh seems to be disappearing into picky jobs worth land quicker than I
feared.
 
S

santosh

jacob said:
santosh said:
jacob said:
Richard Heathfield wrote:
jacob navia said:
H. is arguing that strncmp is not a string comparison function.
Heathfield
That's right.
[snip]

Yes, I agree that it's a comparison function. So what?

OK. I give up.

Are you really saying you don't know the difference between a comparison
function and string comparison function?

The crucial difference between strcmp and strncmp is that the former
_needs_ it's arguments to be null-terminated strings while the latter
doesn't. There is a crucial difference between an array of characters,
(which needn't, but could be, a string), and a string.

Look:

1) The standard names EXPLICITELY strncmp a "comparison functions" in
the section String handling.
2) strncmp starts with the prefix "str"
3) Contrary to memcmp, strncmp will STOP the comparison at a zero byte,
i.e. it has STRING SEMANTICS!

Yes, but it doesn't _require_ it's arguments to be strings.
But you go on telling that it is not a string comparison function.

At the very least I'd say it's a sub-string comparison function.

<snip>
 
J

jacob navia

santosh said:
At the very least I'd say it's a sub-string comparison function.

YES!

That's why it has the "n" integer argument. At most n chars comparison.
 
C

Charlie Gordon

Al Balmer said:
Oh, nonsense. I'm getting tired of this. It seems to me that you
either have experience with a very limited (and incompetent) group of
programmers, or are projecting your own assumptions to the universe.

And it seems to me, you are living on a different planet.
Pick and read samples from real world C programs that use the stinker and
see for yourself how inappropriate the function is for most of the cases.

http://www.google.com/codesearch?q=strncpy+sizeof

You can also look at misuses in the glibc source itself.
 
C

Charlie Gordon

Richard Heathfield said:
Richard Weeks said:
Here is an example of a *good* use of strncpy (which is otherwise not
terribly well-written, but I've tried to make it as clear as possible):

char date[25] = "";
char *d = asctime(&tmstruct);
strncpy(date, d + 11, 9); /* hh:mm:ss */
strncpy(date + 9, d, 4); /* nnn */
strncpy(date + 9 + 4, d + 8, 3); /* dd */
strncpy(date + 9 + 4 + 3, d + 4, 4); /* mmm */
strncpy(date + 9 + 4 + 3 + 4, d + 20, 4); /* yyyy */

That's what it's for - building a record a piece at a time by copying data
from a record-like (multiple field) source.

And it does that job perfectly well.

Nonsense! The right tool for the job above is memcpy in all cases.
strncpy can be used for that, but is not the right tool, sprintf could have
been used too with better readability and even worse performance.
 
C

Charlie Gordon

Richard Heathfield said:
Tor Rustad said:


The first mistake I found is in the first sentence: "length-bounded string
functions such as strncpy()". Finding other mistakes is left as an
exercise for the reader.

Finding teachings is a better reason to read this paper.

As far as shortcomings, I personally do not like the API they chose for
strlcpy and strlcat: I would pass the size of the destination array as the
second argument instead of the third.
 
C

Charlie Gordon

"Tor Rustad" <[email protected]> a écrit dans le message de
(e-mail address removed)...
For the special case you describe, I would rather write something like:

n = sprintf(dest, "%.*s", max, src);

Achtung Minen!

max is not the size of the destination array ``dest'', it should be at most
one less than that, and n will not exceed max, so truncation cannot be
detected. A better approach is this:

n = snprintf(dest, size_of_dest, "%s", src);

if (n >= size_of_dest) {
/* truncation occurred */
}
 
C

Charlie Gordon

Tor Rustad said:
I don't consider truncation a feature at all, but rather way to implement
run-time recovery.

If destination buffer doesn't have the required size to hold all the data,
it's typically a programming fault, and silencing such a thing, is IMO not
the way solid code should be.

Whether it is a feature or a fault depends on context.
Detecting truncation with strlcpy and strlcat is as easy as detecting
failure from malloc.

if (strlcpy(dest, src, size) >= size) {
/* truncation occurred */
}

Ignoring truncation can be fine for formating informative output on a
limited width terminal, while it would be typically wrong for computing a
file path.

strcpy_s does not implement truncation, it detects overflow and reports it
in various ways. If you want mere truncation, strlcpy is what you need.
 
R

Richard Heathfield

Charlie Gordon said:
Richard Heathfield said:
That's what [strncpy is] for - building a record a piece at
a time by copying data from a record-like (multiple field) source.

And it does that job perfectly well.

Nonsense!

I can't agree that it's nonsense.
The right tool for the job above is memcpy in all cases.
strncpy can be used for that, but is not the right tool, sprintf could
have been used too with better readability and even worse performance.

Well, here I'm a bit torn, because I kind of agree with you, insofar as, in
that situation, I would use memcpy. Nevertheless, if I saw strncpy being
used in that way in a code review, I'd let it go. It's no less correct or
readable than the same code with memcpy would be.
 
C

Charlie Gordon

Richard Heathfield said:
Charlie Gordon said:
Richard Heathfield said:
That's what [strncpy is] for - building a record a piece at
a time by copying data from a record-like (multiple field) source.

And it does that job perfectly well.

Nonsense!

I can't agree that it's nonsense.

nonsense applies to "perfectly" and "That's what strncpy is for"

strncpy can be used for that, but that is not what it is for. You do not
need the peculiar semantics of strncpy in your example, you merely swing
around them with adequate arguments and data.
The right tool here *is* memcpy.
Well, here I'm a bit torn, because I kind of agree with you, insofar as,
in
that situation, I would use memcpy. Nevertheless, if I saw strncpy being
used in that way in a code review, I'd let it go. It's no less correct or
readable than the same code with memcpy would be.

But it is less efficient, especially with inline expansion and fixed widths.
strncpy here is just not "le mot juste"
 
R

Richard Heathfield

Charlie Gordon said:

But it is less efficient, especially with inline expansion and fixed
widths. strncpy here is just not "le mot juste"

Whether it is less efficient is not a matter for speculation, but for
measurement.
 
T

Tor Rustad

Flash said:
Tor Rustad wrote, On 04/10/07 01:07:
[...]
The problem isn't that I can't imagine such a usage, but that this use
case is rather a typical programming *fault*. So, I deliberately put
the assert() in there, to catch it.

For the special case you describe, I would rather write something like:

n = sprintf(dest, "%.*s", max, src);

I would not because you are needlessly calling a more complex function.
I would also consider it to be a micro-*de*optimisation, i.e. using
something that looks like it will be less efficient for no good reason


Well, the database experts hardly need any help, to construct an
effective copy-and-truncate function. My example above, was a quick and
simple C solution, for the rare case I would need such a function
myself, which so far has been... approx *zero* times. :)
 
T

Tor Rustad

Al said:
Truncation is what it does with overlength sources. That's what it's
for.

I don't know why you make such a big deal out of this, to avoid buffer
overflow, the destination *string*, simply has to get truncated on
over-sized input.

Considering usual programming faults, a feature... that lead to
hard-to-audit code. When performing code audit, I prefer to focus on the
non-trivial cases, rather than wasting energy on some "clever" features.

Then why an assert? What's wrong with just returning the length of the
source, allowing the user to check whether it's longer than the size
copied? As I understand it, that's what the conventional
implementation does.

We should differentiate between *dynamic* strings, and *fixed-sized*
strings. The strl* functions was designed for fixed-sized strings, if
you want to handle strings dynamically, I suggest you to use some
another API's for that.

When operating on *fixed-sized* strings, it is rather artificial to
construct cases, where you like to silence truncations.
 
C

Charlie Gordon

Richard Heathfield said:
Tor Rustad said:


Well, obviously I disagree. Let me explain why.


So are those of memcpy, memmove, memcmp, memchr, and memset, which are not


So does strncmp, which is not a string processing function either. So the
prefix str is not sufficient to qualify a function as being a "string
function".

Furthermore, there are several functions that require strings as input but
which do not start "str" - *printf, *scanf, atoi, atod, atol, perror,
fopen, to name but a few. These aren't what we might normally think of as
"string functions", but they do at least require strings as input.

strncpy does *not* require even one string as input. It is therefore
somewhat difficult to see how we can justify calling it a "string
function", despite its (badly-chosen) name.

Since you are nitpicking on every meaningless detail, you should also note
that none of atoi, atod, atol, or strto* require strings as input. As long
as the char array argument contains a delimiter, they are required to
attempt to parse it as a number and stop right after that. The fact the
Standard refers to their argument as a string and insist on splitting it in
3 parts with the latter '\0' terminated should probably be considered a
defect, because it is an unneeded constraint.

The Standard unambiguously refers to all functions defined in <string.h> as
string functions, notably in 7.21 String handling, 7.21.1 String function
conventions.
 
M

Malcolm McLean

jacob navia said:
Keith Thompson wrote:
[snip]
The real lesson: assuming that the C standard library is a consistent
and coherently designed interface is dangerous. It isn't. Once you
understand that, you'll probably be ok.

But isn't that acknowledging that this part of the language
needs reworking?

Those _s functions like fopen_s and others proposed in that
Technical Report are a start isn't it?
Kind of. The standard library was designed in the 1970s. Things have moved
on since then, and some decision which seemed sensible at the time we now
know are wrong, or the relaxation of memory and processor constraints has
made them wrong.

However I fail to see what fopen_s adds in terms of safety. It seems to me a
totally pointless change to the interface, workable but made for the purpose
of changing it.
 
C

Charlie Gordon

Richard said:
The reply above is valid for ANY form of C programming.

i=i++

can be potentially lethal too if you dont know what you are doing.

For gods sake, leave strncpy alone. It does what it is documented to do.

strtok and gets are the ones to diss.

strtok and gets also do what they are documented to do, yet you agree they
should be deprecated.
strncpy is so easy to misuse and so widely misused that it should be more
actively scrutinized.
A compiler warning seems appropriate for all of them.
 
M

Malcolm McLean

Richard Heathfield said:
char *p;
printf("If you use printf wrongly, you can get bad results: %s\n", p);

Does that mean we should drop printf from the standard library?
There's certainly a case for a language that never shows undefiend behaviour
on an output function. Unfortunately achieving this usually means an
unacceptable performance impairment for C - you'd have to mark the pointer
as uninitialised.

There is a difference between can be misused and invites misuse. Labelling a
vial of hydrochloric acid "drink me" is a case in point, though of course
wise little girls always check for another label saying "poison". On the
other hand if we label a vial of ethanol "JD" a foolish man might drink the
whole bottle at one go, but we can;t run the world for such people.
 
?

=?iso-2022-kr?q?=1B=24=29CHarald_van_D=0E=29=26=0F

Since you are nitpicking on every meaningless detail, you should also
note that none of atoi, atod, atol, or strto* require strings as input.

The behaviour is undefined if you do

atoi((char [4]) { "123x" })
As long as the char array argument contains a delimiter, they are
required to attempt to parse it as a number and stop right after that.

They are not. Unless there is specific text saying otherwise, they are
permitted to look for the end of the string, and then scan backwards.
They do not have to do this intelligently. They may crash (or worse) on
non-string arguments.
The fact the Standard refers to their argument as a string and insist on
splitting it in 3 parts with the latter '\0' terminated should probably
be considered a defect, because it is an unneeded constraint.

You ackownledge here that the standard does require a string argument.
You are correct that this is requirement is not necessary, but that
doesn't make it any less of one.
The Standard unambiguously refers to all functions defined in <string.h>
as string functions, notably in 7.21 String handling, 7.21.1 String
function conventions.

It is not unambiguous. 7.21.1 also addresses the typedef size_t and the
macro NULL, neither of which are functions, let alone string functions.

And "notably" suggests there are other less notable references to the
<string.h> functions as string functions. I cannot find any. Do you have
any other examples?
 
T

Tor Rustad

Richard said:
Tor Rustad said:


Well, obviously I disagree. Let me explain why.


My point was, what you called a "mistake", is rather what rest of the
world call these functions, namely "string functions".

Since "str" is a shorthand for "string", it is pedantry to me, calling
it a *mistake* of the paper, and using the C standard (which is
responsible for the shorthand) to argue otherwise.

When you as a c.l.c regular state:

"Finding other mistakes is left as an exercise for the reader."

I expect a low-class paper with real technical issues, not that you
referred to some common practice wording.
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,071
Latest member
MetabolicSolutionsKeto

Latest Threads

Top