Pointer to function Prototype - c

i am trying to figure out what those prototypes mean
1.int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
2.int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (* fpCalculation[3]) (const char *));
3.int* (*(*fpData)(const char *))(int (*paIndex)[3] ,
int (* fpMsg) (const char *),
int (* fpCalculation[3]) (const char *));

First you should find actual variable which is being declared. In all 3 examples this is fpData. Then you should start to read declaration staring from this variable moving from inside to outside.
So, let us begin with first example. We see fpData, so we say "fpData is...", then we see "*" before "fpData", so we say "fpData is pointer to...", then we see function type declaration outside of *fpData, so we say "fpData is pointer to function...". Then we should read types of arguments and result of this function.
Well, you can read types for all 3 arguments without problems. They are:
"paIndex is pointer to array of length 3 of ints"
"fpMsg is pointer to function from const char * to int"
"fpCalculation is array of length 3 of pointers to function from const char * to int"
In the last argument you should note that [3] has the higher priority than "*". I mean that while reading declaration from inside to outside you should read first array and then pointer. I. e. int *a[3] is "a is array of length 3 of pointers of int" and not "pointer to array".
Assuming all this I think you can read 2nd declaration without problems.
Now you should learn this: type of function result is written outside (i. e. BEFORE AND AFTER) of everything else.
Let us consider this:
char (*(*fp)(int))(double)
What this means? Well let's start reading, "fp is pointer to function which takes int and returns... what?" Well, we already have read (*fp)(int) part. Now we want to read everything else. And we want to understand what is result type of function we already read. And now we should note that result of function is the thing which is written OUTSIDE (i. e. BEFORE and AFTER) of everything else, i. e. outside of what we already read.
So, we have read (*fp)(int). Everything else, i. e. char (*XXX)(double) is return type for function we already read. So, well, let's continue reading. Finally we will get this:
"fp is pointer to function which gets int and returns pointer to function which gets double and returns char".
Now you can read 3rd declaration without problems

The C gibberish ↔ English link that chux posted still looks like gibberish to
me. So I'll try to sound more human:
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
This declares a function pointer fpData that returns a pointer to int. The
function takes 3 variables of the following types:
paIndex is a pointer to an int array of dimension 3. This can be used for
example when you have this:
void bar(int (*paIndex)[3])
{
}
void foo(void)
{
int fields[5][3] = { {1,1,1}, ... };
bar(fields);
}
fpMsg is a function pointer that returns an int. The function takes one
arguments only, a const char* (a string basically).
fpCalculation is an array of dimension 3 of function pointers that return
int. The functions take on argument only: a const char*.
This is a beast of a function pointer, it works in an evironment like this:
#include <stdio.h>
int msg(const char *name)
{
printf("msg: %s\n", name);
return 0;
}
int abc1(const char *name)
{
printf("abc1: %s\n", name);
return 0;
}
int abc2(const char *name)
{
printf("abc2: %s\n", name);
return 0;
}
int *scary_function(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *))
{
fpMsg("fpMsg");
fpCalculation[0]("fpCalculation0");
fpCalculation[1]("fpCalculation1");
fpCalculation[2]("fpCalculation2");
for(int i = 0; i < 4; ++i)
{
for(int j = 0; j < 3; ++j)
{
printf("%-3d ", paIndex[i][j]);
}
puts("");
}
return NULL;
}
void foo(void)
{
int matrix[4][3] = { {1,2,3}, {4,5,6}, {7,8,9}, {10,11,12} };
int (*fpcalcs[3])(const char*) = { msg, abc1, abc2 };
int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
fpData = scary_function;
// calling the function through the function pointer
fpData(matrix, msg, fpcalcs);
}
int main(void)
{
foo();
return 0;
}
The output of this is
msg: fpMsg
msg: fpCalculation0
abc1: fpCalculation1
abc2: fpCalculation2
1 2 3
4 5 6
7 8 9
10 11 12
So I've explained in detail how to parse the declaration of these function
pointers. Now try understanding the other 2 yourself, if you still have problems,
post a comment.

1.int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *), int (*fpCalculation[3]) (const char *));
Here, fpdata is pointer to a function which takes three arguments and returns a pointer to an integer. The arguments are as follows:
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
2.int* (*fpData[2])(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
In this case, fpdata is array of 2 function pointers, and each function takes three arguments -
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
The return type is a pointer to an integer
3.int* (*(*fpData)(const char *))(int (*paIndex)[3] , int (* fpMsg) (const char *), int (* fpCalculation[3]) (const char *));
Finally, fpdata is a pointer to a function which takes three arguments -
pointer to 3 elements integer array,
pointer to a function which takes const char pointer as an argument and return type int,
array of 3 function pointers and each function takes const char pointer as an argument and return type is int
The return type is a function pointer which takes const char pointer as argument and return type is pointer to an integer.

int* (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));
it is function prototype declaration.
Where fpData is a function name, function that takes three arguments:
int (*paIndex)[3]
int (* fpMsg) (const char *)
int (*fpCalculation[3]) (const char *)
…and returns a function pointer [pointer to a function that take no argument but returns pointer to an integer].
Details :: Given function can be written as below
typedef int* (*ret_func_ptr) ();
ret_func_ptr (*fpData)(int (*paIndex)[3] , int (* fpMsg) (const char *),
int (*fpCalculation[3]) (const char *));

Related

C Code: Pass string from one function to another function

The main problem is: as soon as I send a string from one function to another, this second function doesn't really get the string as a parameter.
In detailled:
I have a function void myfunc() contains a word. This word should be send to another function, so it can count the length of it. That's what I've written so far:
void myfunc(int (*countlength)(char ch)){
char word[10] = "Hello\n";
int result = countlength(&word);
printf("Length of word: %d\n", result);
}
The word is being send to this function countlength(char* word):
int countlength(char* word) {
int length = strlen(word);
return length;
}
However the function countlength() can't count it's length and I don't know why...
The thing is, it works when the word is in the main function. Does anybody know why my Code doesn't work?
Two mistakes:
void myfunc(int (*countlength)(char ch)){
should be
void myfunc(int (*countlength)(char* ch)){
instead, as the function accepts char pointers.
Secondly,
int result = countlength(&word);
should be
int result = countlength(word);
as word is already a char*.
What you're passing to the function doesn't match what it's expecting.
&word has type char (*)[10], i.e. a pointer to an array of size 10. The function expects a char *, so just pass word. Arrays are converted to a pointer to their first element when passed to a function, so the types will match.
This parameter declaration of a function pointer
int (*countlength)(char ch)
does not correspond to the function declaration used as an argument for this parameter
int countlength(char* word)
So you need to declare the parameter like
int (*countlength)(char *ch)
In fact the identifier ch is redundant. You could just write
int (*countlength)(char *)
That is the declaration of the function myfunc will look like
void myfunc(int (*countlength)(char *));
You declared a character array within the function like
char word[10] = "Hello\n";
So the expression used as an argument in this call
countlength(&word)
has the type char ( * )[10] instead of the expected type char *.
There is no need to use the address of operator. The array designator used as an argument in this call
countlength( word )
is implicitly converted to a pointer to the first element of the array and has the type char *.
This function
int countlength(char* word) {
int length = strlen(word);
return length;
}
does not change its argument. So it should be declared at least like
int countlength( const char* word) {
int length = strlen(word);
return length;
}
The used standard C string function strlen has the return type size_t. In general an object of the type int can be not enough large to store possible lengths of strings.
So the function should be declared like
size_t countlength( const char* word) {
return strlen(word);
}
Thus returning to the function myfunc it should look like
void myfunc( size_t ( *countlength )( const char * ) )
{
char word[10] = "Hello\n";
size_t result = countlength( word );
printf( "Length of word: %zu\n", result );
}
Well; if you use the code like this, it's working just fine
When you declare an array, its name has a type of a pointer so here word has a type of char* and it's the pointer of the array's first element
#include <stdio.h>
#include <string.h>
int countlength(char* word) {
int length = strlen(word);
return length;
}
void myfunc(){
char word[10] = "Hello\n";
int result = countlength(word);
printf("Length of word: %d\n", result);
}
main(){
myfunc();
}
Length of word: 6

Swapping 2 string pointers with a function whose parameters are void **

The following code doesn't compile:
void swap(void **p, void **q) {
void *tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
int main(void) {
char *s[] = {"help" , "please"};
swap(&s[0], &s[1]);
return 0;
}
While this code compiles and runs just fine:
void swap(void **p, void **q) {
void *tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
int main(void) {
char *s[] = {"help" , "please"};
swap((void **) &s[0], (void **) &s[1]);
return 0;
}
Why is the casting necessary ?
Yeah, so in addition to the already existing answers that point out that void ** is not the same as char **: your code invokes undefined behavior because of the incompatible pointer types. Here's what you actually want:
void swap(void *p1, void *p2, size_t size)
{
unsigned char buf[size];
memcpy(buf, p1, size);
memcpy(p1, p2, size);
memcpy(p2, buf, size);
}
And call it like this:
const char *s[] = { "help", "please" }; // also note the use of `const' for string literals
swap(&s[0], &s[1], sizeof(s[0]));
You have incompatible pointer assignment error in first code. In C type of a string literal is char[N] Where N is number of chars. Note in most of expressions char[N] easily decays into char*
According to your declaration char *s[] = {"help" , "please"}; type of s[i] is char* (actaully char[N] decayed into char*).
When you pass &s[i] then you are passing char** that is incompatible with void**. Second code works because you typecast into void** in function calling.
void* can be assigned any address type but its void** that has to be assigned address of void* type variable.
If you only having array of strings then in first version of swap function you can replace void by char then you can all without typecast.
The casting makes the example compile because of what you are passing the function.
char *var[]; is in many ways the same as char **var;
With that being said, you are passing the function a reference/address one of the members of the array (s[0]).
Another more prominent issue, is that the function accepts void pointers, and is passed character pointers (without the casting).

Sort char pointer array in C

I am trying to sort array of char pointers, for that purpose I use qsort function, but I can't understand what I am doing wrong and how I can sort that array.
int StringCompare( const void* a, const void* b)
{
char const *char_a = (char const *)a;
char const *char_b = (char const *)b;
return strcmp(char_a, char_b);
}
int main() {
char *a[] = { "Garima",
"Amit",
"Gaurav",
"Vaibhav"
};
int n;
qsort( a, 4, sizeof(char*), StringCompare);
for (n=0; n<4; n++)
printf ("%c ",*a[n]);
}
The Output is: G A G V
The issue is that the values passed to the sort function (a.k.a StringCompare) are pointers into the a array. In other words, they are of type const char **.
You need to instead declare char_a and char_b as const char **, and dereference them in the call to strcmp:
int StringCompare( const void* a, const void* b)
{
char const **char_a = a;
char const **char_b = b;
return strcmp(*char_a, *char_b);
}
Also note the casts are unnecessary.
proper comparator:
int StringCompare( const void* a, const void* b)
{
char const *char_a = *(char const **)a;
char const *char_b = *(char const **)b;
return strcmp(char_a, char_b);
}
NOTE:
according to sort description comparator function is:
compar
Pointer to a function that compares two elements.
This function is called repeatedly by qsort to compare two elements.
It shall follow the following prototype:
int compar (const void* p1, const void* p2);
so, it receives not a char*, but char**
proper output cycle:
for (n=0; n<4; n++)
printf ("%s ", a[n]);
Define your StringCompare function this way:
int StringCompare(const char **a, const char **b)
{
return strcmp(*a, *b);
}
No need to clutter the code with explicit casting because you can implicitly cast a void pointer to any other pointer type.
If you want to sort char-arrays for the first letters, you could implement a function, that looks at the (unsigned) values of the first char in the array. As they are all equal to the numbers in the ASCII-standards. But you have to be careful if you mix upper case chars with lower case chars.
I know... its not a some special implemented function, but I once programmed it that way and it worked.

Pointers On Pointers

#include <stdio.h>
#include <string.h>
void F1(void *comp, void *record){
int complen = strlen((char *)comp), recordlen = *(int *)record;
*(int *)record = complen>recordlen ? complen : recordlen;
}
void F2(void *comp, void *ans){
if(!*(char **)ans)
*(char **)ans = (char *)comp;
else if(strcmp((char *)comp, *(char **)ans) < 0)
*(char **)ans = (char *)comp;
}
void ProcessStrings(char ***vals, void* (*fp)(char *, void *), void *champ){
char **copy = *vals;
while(*copy){
fp(*copy++, champ);
}
}
int main() {
char *strings1[][100] = {{"beta", "alpha", "gamma", "delta", NULL}, {"Johnson", "Smith", "Smithson", "Zimmerman", "Jones", NULL}, {"Mary", "Bill", "Bob", "Zoe", "Annabelle", "Bobby", "Anna", NULL}};
int maxLen = 0;
char *minString = NULL;
ProcessStrings(strings1, F1, &maxLen);
ProcessStrings(strings1, F2, &minString);
printf("Strings1: Max length is %d and min is %s\n", maxLen, minString);
}
A quick background...function F1 supplies the max length of a list of strings to it's second parameter. F2 supplies the minimum string in terms of ASCII value.
My error message states that I'm passing an incompatible pointer type to process strings. When I draw out the pointers, I feel as though I am not. Help?
You are passing an incompatible pointer type indeed.
strings1 is a 2D array of pointers to chars. Note, that a 2D array elements in C are laid out sequentially row after row, while the function expects to see a pointer after the first dereference of strings1 inside the ProcessStrings.
If you want you code to work correctly, you need to either pass the following construct to ProcessStrings
char **strings2[] = {
strings1[0],
strings1[1],
strings2[2]
};
or to change the the function to work with a pointer to an array of 100 char pointers:
void ProcessStrings2(char * (*vals)[100], void (*fp)(void *, void *), void *champ){
Btw, your function seems to process only the first row of strings.

convert pointer to pointer to void pointer

When I'm learning to use qsort to sort an array of string, there is a question puzzled me.
For example, to sort the following s
char *s[] = {
"Amit",
"Garima",
"Gaurav",
"Vaibhav"
};
To use the qsort, you must provide a comparison function like the
following function cstring_cmp I guess in the qsort function, the type of parameter to be passed to the function cstring_cmp is char**. How to convert a char** to a void*? Why can we convert a char** to a void*?
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
return -strcasecmp(*ia, *ib);
/* return the negative of the normal comparison */
}
Your question seems a bit vague but I'll give it a go anyway. To answer how, you can convert any pointer type to any other pointer type in C by simply casting. To answer why, well that's how C is defined.
The qsort() function requires a function with the given prototype (with const void *) parameters. This is because qsort() is unaware of the actual data type you are sorting, and must use a consistent function prototype for the comparison callback. Your comparison callback is responsible for converting the const void * parameters to pointers to the actual types in your array, in your case const char **.
The example you provide is being setup to ask qsort() to sort an array of char pointers (char *). This comparator you're providing is given each 'pair' of items the algorithm needs, by address. two char pointers. the address qsort() uses is based on the root address you give it, adding size-bytes per "item". Since each "item" is a char*, the size of each item is, in fact, the size of a pointer.
I've modified the comparator to demonstrate what is being compared, and what the addresses are that are being passed in. you will see they are all increments off the base address of the array containing all the char *s.
char *mystrings[] =
{
"This",
"is",
"a",
"test",
"of",
"pointers",
"to",
"strings"
};
int cstring_cmp(const void *a, const void *b)
{
const char **ia = (const char **)a;
const char **ib = (const char **)b;
printf("%p:%s - %p:%s\n", a, *ia, b, *ib);
return -strcasecmp(*ia, *ib);
}
int main(int argc, char *argv[])
{
printf("Base address of our pointer array: %p\n\n", mystrings);
qsort(mystrings, sizeof(mystrings)/sizeof(mystrings[0]), sizeof(char*), cstring_cmp);
for (size_t i=0; i<sizeof(mystrings)/sizeof(mystrings[0]);i++)
printf("%s\n", mystrings[i]);
return 0;
}
produces the following output:
Base address of our pointer array: 0x100006240
0x100006240:This - 0x100006260:of
0x100006260:of - 0x100006278:strings
0x100006240:This - 0x100006278:strings
0x100006248:is - 0x100006240:strings
0x100006278:This - 0x100006240:strings
0x100006250:a - 0x100006240:strings
0x100006270:to - 0x100006240:strings
0x100006258:test - 0x100006240:strings
0x100006260:of - 0x100006240:strings
0x100006268:pointers - 0x100006240:strings
0x100006260:of - 0x100006240:strings
0x100006240:test - 0x100006248:This
0x100006248:test - 0x100006250:to
0x100006240:This - 0x100006248:to
0x100006260:of - 0x100006268:pointers
0x100006268:of - 0x100006270:a
0x100006270:a - 0x100006278:is
0x100006268:of - 0x100006270:is
to
This
test
strings
pointers
of
is
a
A even less visualized one:
int cstring_cmp(const void *a, const void *b){
return -strcasecmp((char *)(*((char **)a)), (char *)(*((char **)b)));
}
But you can see , a and b are char **, and they are dereferenced and become char * and passed to strcasecmp.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int cstring_cmp(const void *a, const void *b){
return -strcasecmp((char *)(*((char **)a)), (char *)(*((char **)b)));
}
int main(){
char *s[] = { "Amit",
"Garima",
"Vaibhav",
"Gaurav"};
qsort(s, 4, sizeof(char *), cstring_cmp);
printf("%s\n%s\n%s\n%s\n", s[0], s[1], s[2], s[3]);
return 0;
}
Output:
Vaibhav
Gaurav
Garima
Amit
It is legal to cast any pointer to char * or void * because void * means a pointer to a memory (RAM or virtual) byte.

Resources