473,749 Members | 2,660 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Comparison function in qsort()

Hello,

I've come across the following comparison function used as the 4th
parameter in qsort()

int cmp(const void *px, const void *py)
{
const double *x = px, *y = py;
return (*x > *y) - (*x < *y);
}

It came "as-is" i.e. no comments.

Is it good style to write comparison functions that way?

Should the return values be made more explicit? Or would it be enough to
add comments explaining why the function (usually) works?

--
Regards, Spoon
Apr 12 '06 #1
14 5019
Spoon schrieb:
Hello,

I've come across the following comparison function used as the 4th
parameter in qsort()

int cmp(const void *px, const void *py)
{
const double *x = px, *y = py;
return (*x > *y) - (*x < *y);
}

It came "as-is" i.e. no comments.

Is it good style to write comparison functions that way?

Should the return values be made more explicit? Or would it be enough to
add comments explaining why the function (usually) works?


Depends. Possible points of view:
1) "Everyone" knows that relational operators in C return either 0
or 1, thus Everyone can figure it out.
2) If it is too complicated for Everyone, then it should be commented.
3) If it has to be explained so that Everyone understands it, then it
should not be written this way -- too clever for its own good.
4) Write the code as explicit and simple as possible:
- modern compilers on host PCs can optimise it better,
- there is no danger of misunderstandin g
5) As 4) but if you found out by measuring that cmp() is a bottleneck,
then try this out as one alternative; use the alternative which is
fastest and comment it clearly and explain why you did what you did.
6) As 5) but consider that probably the problem is using qsort(), as
well; you have indirection and function call overhead. It may be better
to write a dedicated double array sort. This makes the above construct
once more unnecessary. Use a well-tested out-of-the-book/from-the-CD
algorithm.

Which alternative you use depends on the people you work with
and the constraints you work under (coding guidelines etc.).
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Apr 12 '06 #2

"Spoon" <none> wrote in message
news:44******** *************** @news.free.fr.. .
Hello,

I've come across the following comparison function used as the 4th
parameter in qsort()

int cmp(const void *px, const void *py)
{
const double *x = px, *y = py;
return (*x > *y) - (*x < *y);
}

It came "as-is" i.e. no comments.

Is it good style to write comparison functions that way?

Should the return values be made more explicit? Or would it be enough to
add comments explaining why the function (usually) works?

--
Regards, Spoon


It's (almost) never a good style to write ANY function with no comments at
all.
Most software development groups have some sort of coding standards.
Mine require ALL functions to specify what the function is for,
describe all parameters, and describe the return value.
In addition, such show-off coding without explaining why it works
can often lead to trouble later on when someone else with less
expertise tries to modify the code, or port it to a different language
(where, for example, boolean true is not 1).

In the above case, the coding is rather silly.
return (*x - *y);
works just as well, with or without the parentheses,
if the function is used only as a qsort() comparer.

If the answer MUST be -1, 0, or +1 for some reason (like it is used
by in some other comparison that requires that), it should be
documented as such.
--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project
Apr 12 '06 #3
"Fred Kleinschmidt" <fr************ ******@boeing.c om> writes:
"Spoon" <none> wrote in message
news:44******** *************** @news.free.fr.. .
Hello,

I've come across the following comparison function used as the 4th
parameter in qsort()

int cmp(const void *px, const void *py)
{
const double *x = px, *y = py;
return (*x > *y) - (*x < *y);
}

It came "as-is" i.e. no comments.

Is it good style to write comparison functions that way?

Should the return values be made more explicit? Or would it be enough to
add comments explaining why the function (usually) works?
[snip] In the above case, the coding is rather silly.
return (*x - *y);
works just as well, with or without the parentheses,
if the function is used only as a qsort() comparer.


No, it wouldn't. Consider what happens if the subtraction overflows.
Or, since the operands are of type double, consider *x==0.5, *y==0.25;
the result of the subtraction is 0.25, which yields 0 when
(implicitly) converted to int.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Apr 13 '06 #4
Fred Kleinschmidt wrote:
"Spoon" <none> wrote in message
news:44******** *************** @news.free.fr.. .
Hello,

I've come across the following comparison function used as the 4th
parameter in qsort()

int cmp(const void *px, const void *py)
{
const double *x = px, *y = py; ^^^^^^

Note that this is comparing doubles
return (*x > *y) - (*x < *y);
}

It came "as-is" i.e. no comments.

Is it good style to write comparison functions that way?

Should the return values be made more explicit? Or would it be enough to
add comments explaining why the function (usually) works?

--
Regards, Spoon
It's (almost) never a good style to write ANY function with no comments at
all.
Most software development groups have some sort of coding standards.
Mine require ALL functions to specify what the function is for,
describe all parameters, and describe the return value.


Agreed.
In addition, such show-off coding without explaining why it works
can often lead to trouble later on when someone else with less
expertise tries to modify the code,
In this case, as the function is being passed to qsort its purpose is
fairly obvious, and anyone who could not at least work out what it is
doing and how it works is not ready to be working on their own as a
maintenance programmer.
or port it to a different language
(where, for example, boolean true is not 1).
When translating between two languages it is better in my experience to
look at the purpose of regions of code and write appropriate
replacements than to simply translate on a function by function basis.
In the above case, the coding is rather silly.
return (*x - *y);
works just as well, with or without the parentheses,
if the function is used only as a qsort() comparer.
No it doesn't. Or do you think that 0.1 - 0 is guaranteed to produce a
positive number rather than 0?

Your suggestion is not even guaranteed for int, since INT_MIN - 1 will
overflow, and the behaviour on overflow is undefined.
If the answer MUST be -1, 0, or +1 for some reason (like it is used
by in some other comparison that requires that), it should be
documented as such.


Agreed, but IMHO the code was probably written that way for correctness
rather than to produce exactly +0, -1 or 0.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Apr 13 '06 #5
Keith Thompson <ks***@mib.or g> writes:
"Fred Kleinschmidt" <fr************ ******@boeing.c om> writes:
"Spoon" <none> wrote in message
news:44******** *************** @news.free.fr.. .
Hello,

I've come across the following comparison function used as the 4th
parameter in qsort()

int cmp(const void *px, const void *py)
{
const double *x = px, *y = py;
return (*x > *y) - (*x < *y);
}

It came "as-is" i.e. no comments.

Is it good style to write comparison functions that way?

Should the return values be made more explicit? Or would it be enough to
add comments explaining why the function (usually) works?

[snip]
In the above case, the coding is rather silly.
return (*x - *y);
works just as well, with or without the parentheses,
if the function is used only as a qsort() comparer.


No, it wouldn't. Consider what happens if the subtraction overflows.
Or, since the operands are of type double, consider *x==0.5, *y==0.25;
the result of the subtraction is 0.25, which yields 0 when
(implicitly) converted to int.


The code above, "return (*x > *y) - (*x < *y);", is also probably
better-behaved in the presence of infinities and NaNs, at least quiet
NaNs.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Apr 13 '06 #6
Fred Kleinschmidt wrote:
"Spoon" <none> wrote in message

I've come across the following comparison function used as the 4th
parameter in qsort()

int cmp(const void *px, const void *py)
{
const double *x = px, *y = py;
return (*x > *y) - (*x < *y);
}

It came "as-is" i.e. no comments.

Is it good style to write comparison functions that way?

Should the return values be made more explicit? Or would it be
enough to add comments explaining why the function (usually) works?
.... snip ...
In the above case, the coding is rather silly.
return (*x - *y);
works just as well, with or without the parentheses,
if the function is used only as a qsort() comparer.


No it doesn't. That is subject to overflow and undefined
behaviour. The recommended code may have been due to me, and
caters to avoidance of flushing of instruction streams. It
specifies the types being compared in exactly one place, and works
all the time.

IMO there are very few non-beginners who would not understand the
code. There are many coders who fail to understand the reasons for
the code.

--
"If you want to post a followup via groups.google.c om, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell. org/google/>
Also see <http://www.safalra.com/special/googlegroupsrep ly/>
Apr 13 '06 #7
On Thu, 13 Apr 2006 00:37:39 +0100,
Flash Gordon <sp**@flash-gordon.me.uk> wrote
in Msg. <qi************ @news.flash-gordon.me.uk>
In this case, as the function is being passed to qsort its purpose is
fairly obvious, and anyone who could not at least work out what it is
doing and how it works is not ready to be working on their own as a
maintenance programmer.


A side note: I always like to name my qsort cmp functions starting with
'by_' because it makes for better English:

qsort(customer, ..., by_name);

robert
Apr 13 '06 #8
Robert Latest <bo*******@yaho o.com> wrote:
Flash Gordon <sp**@flash-gordon.me.uk> wrote
In this case, as the function is being passed to qsort its purpose is
fairly obvious, and anyone who could not at least work out what it is
doing and how it works is not ready to be working on their own as a
maintenance programmer.


A side note: I always like to name my qsort cmp functions starting with
'by_' because it makes for better English:

qsort(customer, ..., by_name);


Hey, that's not a bad idea at all! I might adopt that.

Richard
Apr 18 '06 #9
Richard Bos said:
Robert Latest <bo*******@yaho o.com> wrote:
A side note: I always like to name my qsort cmp functions starting with
'by_' because it makes for better English:

qsort(customer, ..., by_name);
Hey, that's not a bad idea at all!


Very good idea, in fact. Nice one, Robert.
I might adopt that.


Too late. I already have the papers right here, signed by a judge.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Apr 18 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
1729
by: Debashish Chakravarty | last post by:
Would it have been a good idea if the comparison function in quicksort took three const void * parameters in, the third one for extra information that might be required to compare the two objects, I think the only way one can pass the information is by using global or static variables.
0
1165
by: Debashish Chakravarty | last post by:
I am sorry, I meant qsort function not quicksort (I know qsort might not implement quicksort) and since I am constrained to use google I cannot reply to my previous post and hence his new post, apologies for the inconvienience.
3
2306
by: Dennis Chang | last post by:
Hi all, I was reading about function pointers and came across something which intrigued me. K&R2 calls qsort (pg.119) within main as so: qsort( (void **) lineptr, 0, nlines-1, (int (*) (void *, void*))(numeric ? numcmp : strcmp) ); I guess what interests me is the nameless function pointer and then the
5
2535
by: Danilo Kempf | last post by:
Folks, maybe one of you could be of help with this question: I've got a relatively portable application which I'm extending with a plugin interface. While portability (from a C perspective) is going to hell just by using dlopen()/LoadLibrary() respectively, I'm still trying to get it as clean as possible. I have a number of different quantums of data and a number of plugins. Since any plugin can (and possibly will) touch any quantum...
6
4467
by: aurgathor | last post by:
Howdy, How do I pass some function a generic comparison function? I figured out one non-generic case, but since this code got parameter declarations in two places, it's obviously not generic. TIA #include <stdio.h>
9
3472
by: christer-sandberg | last post by:
When I typecast a function and call it trough the casted pointer (se code below) I get the warnings: warning: function called through a non-compatible type if this code is reached, the program will abort and the gcc generates abort code for the call. This happens when I use gcc 3.4 but not when I use 3.3. Is there any flag that can change this behavior? I am aware that ANSI-99 says (in 6.3.2.3-8): "If a converted pointer is used to call...
17
3600
by: Charles Sullivan | last post by:
The library function 'qsort' is declared thus: void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); If in my code I write: int cmp_fcn(...); int (*fcmp)() = &cmp_fcn; qsort(..., fcmp); then everything works. But if instead I code qsort as:
9
5087
by: cmk128 | last post by:
Hi Why put * in front of the function name in the declaration? int (*write)(struct inode *, struct file *, const char *, int); thanks from Peter (cmk128@hotmail.com)
26
25604
by: tnowles00 | last post by:
Hi friend, what is the use of function pointer in c language and where it is useful? tell with simple example...? plz help me.
0
8997
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9568
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8257
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6801
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6079
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4709
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4881
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3320
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2218
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.