Can someone explain to me this code from K&R's 'The C Programming Language' book?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
//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.
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 *).
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.
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).
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.)
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:
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.