Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusing line in K&R 5.11 function pointers C

The last parameter of this line in main() makes me lost

// declaration
void qsort(char *linep[], int left, int right, int (*compare)(void *, void*);

// use
main(){
    qsort((void**) lineptr, 0, nlines-1, (int (*)(void*,void*))(numeric ?
    numcmp : strcmp));
}

I understand the ternary operator but let's say numeric == 0 then what does this mean?

(int (*)(void *, void*))strcmp;

Do datatypes of function parameters mismatch?

int strcmp(const char*, const char*);
void qsort( , , , int(*)(void*)(void*);

Can I typecast a function pointer?

like image 549
Pruzo Avatar asked Feb 26 '16 13:02

Pruzo


People also ask

What is a line in K-pop?

Line. A line is a collection of idols within a K-pop group who all have something in common. For example, the dance line is a group's dancers, the maknae line is its younger members, and the '00 line is all of its members who were born in 2000.

What do you call a person who loves K-pop?

Sasaeng: This word is usually followed by fan as in "sasaeng fan," or super obsessed fans who go a little bit over the top in expressing their love for their favorite idols.

What language is K-pop?

K-pop stands for Korean pop, pop being short for pop music. The name for the genre is first recorded in English around 1990–95. Strongly influenced by Western popular music, K-pop took off in 1992 with Seo Taiji and Boys, who incorporated rap, rock, and dance elements into Korean popular music.

What do you call your fav K-pop group?

Your bias is your favourite member of a group; your bias group is your favourite group. Related: ult bias - your absolute favourite member of all idol groups; bias wrecker: a member of a group that makes you want to switch from your current favourite in that group.


2 Answers

In your code, using the cast

  (int (*)(void *, void*))strcmp;

means, strcmp() is a function pointer, which takes two void * arguments and returns an int.

Usually, for function pointers, casting is a very bad idea, as quoting from C11, chapter §6.3.2.3

[...] If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.

but, in your case, for the argument types, char * and void * alias each other, so the typecasted type is compatible with the actual effective type(s), so (at a later point) the function call is defined.

like image 110
Sourav Ghosh Avatar answered Oct 18 '22 04:10

Sourav Ghosh


Yes, you can cast a function pointer to a pointer to a function with a different signature. Depending on your calling convention (who cleans the stack up? The caller or the callee?) calling that function will be bad if there is a different number of arguments or their sizes differ.

Neither is the case here: On your standard architecture (sun workstations, Linux PCs, raspberry PI) the argument pointers to different data types are represented identically so that no harm is expected. The function will read the 4 or 8 byte value from the stack and interpret the memory pointed to as data of the expected type (which it should have though, e.g. don't use a float compare function on strings; it may throw because arbitrary bit patterns can be NaNs etc.).

I wanted to alert you to the fact that today's standard lib's qsort has a different function signature (and semantic) than K&R's example. Today's qsort gets a pointer to the beginning of an element vector and calls the compare function with pointers to the elements in the array; in the case of an array of string pointers, the arguments are pointers to pointers which are not suitable for strcmp(). The arguments have to be dereferenced first. The linux man page for qsort has an example for a strcmp wrapper which does just that. (The man page web export appears somewhat garbled, but is still readable.)

like image 1
Peter - Reinstate Monica Avatar answered Oct 18 '22 04:10

Peter - Reinstate Monica