LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-07-2006, 02:28 PM   #1
frankie_DJ
Member
 
Registered: Sep 2004
Location: NorCal
Distribution: slackware 10.1 comfy, Solaris10 learning
Posts: 232

Rep: Reputation: 32
Can someone explain to me this code from K&R's 'The C Programming Language' book?


Hi everyone,

The following is a code from K&R 'The C Programming Language' and I
can't seem to figure out what is going on. The program is supposed to do a job similar to the unix command sort: it should sort the lines of the input text lexicographicaly or numericaly, based on user's choice.

Code:
#include <stdio.h>
#include <string.h>

#define MAXLINES 5000 /*max #lines to be sorted */
char *linesptr[MAXLINES]; /*pointers to text lines */


int readlines(char *linesptr[],int nlines);
void writelines(char *linesptr[], int nlines);

//these two functions are written elsewhere and I understand
//what they do: readlines stores all the input lines in one big
 //char array and put the pointer (member of linesptr array) at 
//beginning of each; writelines just prints out these lines

void qsort(void *linesptr[],int left, int right, 
int (*comp)(void *, void *));

//this is a sorting procedure which I also understand; the whole 
//point is to illustrate pointers to the functions - user can 
//pick either numerical or lexicographical comparision and use 
//that as a *comp function in the sorting algorithm

main(int argc, char *argv[])
{
int nlines; /* number of input lines read */
int numeric=0; //1 if numeric sort

if (argc>1 && strcmp(argv[1], "-n")==0)
numeric==1;

if ((nlines=readlines(linesptr,MAXLINES))>=0)
{

//THE FOLLOWING LINE IS WHAT I CANNOT UNDERSTAND!
qsort((void **) linesptr, 0,nlines-1,(int (*)(void*,void*))(numeric?numcmp:strcmp));
//WHAT IS (VOID **) DOING? IS IT CASTING LINESPTR? WHY TWO STARS?
//ALSO what is int (*)? WHY NOT int (*comp)?


writelines(linesptr,nlines);
return 0;
}
else
{
printf("input too big to sort\n");
return 1;
}
}
I have been looking at this code for couple of days now, and I just can't figure out what these constructs do. Any help would be appreciated. Ask if you need more clarification of what is the code supposed to do. Thanks

Last edited by frankie_DJ; 11-07-2006 at 02:34 PM.
 
Old 11-07-2006, 03:40 PM   #2
jim mcnamara
Member
 
Registered: May 2002
Posts: 964

Rep: Reputation: 36
Code:
qsort((void **) linesptr, 0,nlines-1,(int (*)(void*,void*))(numeric?numcmp:strcmp));
linesptr is a pointer to a pointer so it is void**
 
Old 11-07-2006, 03:44 PM   #3
soggycornflake
Member
 
Registered: May 2006
Location: England
Distribution: Slackware 10.2, Slamd64
Posts: 249

Rep: Reputation: 31
Quote:
//WHAT IS (VOID **) DOING? IS IT CASTING LINESPTR? WHY TWO STARS?
If a function takes a void*, then you can pass any pointer to it and it will be automatically cast to void (assuming an ANSI C compiler). However, casting is not recursive. A char** (which is what linesptr is) will not be automatically cast to a void**, hence the cast. See the C usenet FAQ for more details on this.

Quote:
//ALSO what is int (*)? WHY NOT int (*comp)?
This is a function type, the name of the function is not relevant here.

A typedef would make this clearer, e.g.

Code:
typedef int (*CmpFunc)(void *, void*);
CmdFunc comp;

qsort((void **) linesptr, 0,nlines-1, (CmpFunc)(numeric?numcmp:strcmp));
 
Old 11-07-2006, 03:48 PM   #4
95se
Member
 
Registered: Apr 2002
Location: Windsor, ON, CA
Distribution: Ubuntu
Posts: 740

Rep: Reputation: 32
OK,

int (*comp)(void *, void *));

This isn't actually a "function," but a pointer to a function. One that is apparently never set to anything, and never used ?

(int (*)(void*,void*))(numeric?numcmp:strcmp)
This is just casting either the function numcmp or strcmp (if numeric is true or false respectively) to one that has the signiture int (*)(void*,void*). This is needed, because if strcmp is defined like this, int strcmp(const char *, const char *), then the compiler will give, at least, a warning, and may be an error. And, for all I know, numcmp is defined like this, int numcmp(int *, int *).

Last edited by 95se; 11-07-2006 at 03:49 PM.
 
Old 11-07-2006, 11:45 PM   #5
frankie_DJ
Member
 
Registered: Sep 2004
Location: NorCal
Distribution: slackware 10.1 comfy, Solaris10 learning
Posts: 232

Original Poster
Rep: Reputation: 32
thank you guys. but I still don't understand why two stars. Function would normaly be called with

qsort(linesptr,left,right, numcp)

If I want to cast linesptr, shouldn't I do

qsort((void *) linesptr,left,right,numcp)

?
 
Old 11-08-2006, 02:47 AM   #6
Wim Sturkenboom
Senior Member
 
Registered: Jan 2005
Location: Roodepoort, South Africa
Distribution: Ubuntu 12.04, Antix19.3
Posts: 3,794

Rep: Reputation: 282Reputation: 282Reputation: 282
You are correct that you normally would pass lineptr. However. qsort wants an array of pointers to void, hence the casting.

When you cast, you must cast to the same 'type'; as lineptr is an array (the first pointer) of pointers (the second pointer) to character strings, you need to cast to array of pointers and hence the two stars in the cast.
 
Old 11-08-2006, 05:33 AM   #7
frankie_DJ
Member
 
Registered: Sep 2004
Location: NorCal
Distribution: slackware 10.1 comfy, Solaris10 learning
Posts: 232

Original Poster
Rep: Reputation: 32
OK, so does that mean that
qsort((void *) linesptr[],...)
would also be correct?

Last edited by frankie_DJ; 11-08-2006 at 05:42 AM.
 
Old 11-08-2006, 11:08 AM   #8
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
use ddd (debugger)
have a look, step through, examine, you may find it useful
in understanding.
 
Old 11-08-2006, 11:24 AM   #9
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Originally Posted by frankie_DJ
OK, so does that mean that
qsort((void *) linesptr[],...)
would also be correct?
Though I remember there are subtle differences between "char *str[]" and "char **str", in this case it would probably be equivalent. (I just don't remember what those subtle differences really are).
 
Old 11-09-2006, 09:44 AM   #10
soggycornflake
Member
 
Registered: May 2006
Location: England
Distribution: Slackware 10.2, Slamd64
Posts: 249

Rep: Reputation: 31
Quote:
Originally Posted by Hko
Though I remember there are subtle differences between "char *str[]" and "char **str", in this case it would probably be equivalent. (I just don't remember what those subtle differences really are).
Technically, they are different types, the former is a pointer to an array of characters, while the latter is a pointer to a pointer to a char. However, since a pointer to an array decays into a pointer to the first element, they are equivalent in practice. (Thus, one may use either e.g. 'int main(int argc, char *argv[])' or 'int main(int argc, char **argv)' without incident.)
 
Old 11-25-2006, 01:35 PM   #11
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
Originally Posted by soggycornflake
Technically, they are different types, the former is a pointer to an array of characters, while the latter is a pointer to a pointer to a char. However, since a pointer to an array decays into a pointer to the first element, they are equivalent in practice. (Thus, one may use either e.g. 'int main(int argc, char *argv[])' or 'int main(int argc, char **argv)' without incident.)
Thanks. Now I also remember one of the implications of this difference. Like it's not possible to initialize a pointer to a pointer to a char, but an array of pointers to a char (array of strings) can be initialized with constant strings:

This is OK:
Code:
char *str_arr[] = {"one", "two"};
But this is not:
Code:
 char **str_arr = {"one", "two"};
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
which programming language is used to do tcp/ip programming?? gajaykrishnan Linux - Networking 9 12-21-2012 05:16 AM
Is K&R's "The C Programming Language" outdated? frankie_DJ Programming 3 09-21-2006 07:39 AM
explain me some c code alaios Programming 4 11-28-2005 11:27 AM
explain me this c code plz alaios Programming 1 06-03-2005 05:32 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:35 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration