This question already has an answer here:
Differences between pointer declaration [duplicate]
(1 answer)
Closed 2 years ago.
in the following function declaration
my_struct* create(char *name);
Is there any difference in the meaning of * in my_struct* and *name?
I understand that char *name means that we will pass a char pointer to the function my_struct called name. I also get that the function will return a pointer to (memory address of) something. What I don't understand is why my_struct* and not *my_struct?
In this declaration
my_struct * create(char *name);
the name of the function is create. The function has one parameter of the type char *, And the function has the return type my_struct *. That is it returns a pointer to an object of the type my_struct.
Is there any difference in the meaning of * in my_struct* and *name
my_struct is a type specifier. So my_struct * is a pointer type. name is identifier that denotes the name of a parameter. The type of the parameter (identifier) name is char *.
Pay attention to that these declarations of the parameter are the same
char* name
char * name
char *name
that is the type of the parameter is char * and the name of the parameter is name.
In a function declaration that is not at the same time its definition names of parameters may be omitted.
So the above function declaration can be also written like
my_struct * create( char * );
Related
I have an assignment to typedef function pointers which can point to main function. I tried something like this but I'm not sure if it's viable.
typedef mainPtr(*f[])(int, char**);
The thing that bothers me is that array size is not defined. How would you do this?
The type of main (in the form you want) is int main(int, char **).
A pointer to that is int (*main)(int, char **).
An array of those is int (*main[])(int, char **).
A typedef of that is typedef int (*mainPtr[])(int, char **);.
Whether you need a size for the array depends on how you will use the type. If you define and initialize an object of this type, its array size will be completed by counting the initializers. For example:
mainPtr p = { main, NULL };
will create an array with two elements.
In other uses, such as declaring a function parameter with this type, you may not need the array to be complete. An array function parameter is automatically adjusted to be a pointer, so the size is discarded anyway. However, if you wish, you could include the size in the typedef.
The syntax is easier if you typedef function itself:
typedef int mainfunc(int, char **);
Then you can use the "normal" pointer syntax:
/* definition of the function pointer*/
mainfunc *mainptr;
/* definitions of the function pointer arrays*/
mainfunc *mainptrarray[5];
mainfunc *mainptrarray1[] = {foo, bar, NULL};
I know about typedef in C, but I got confused when I saw a declaration in the K&R book. The declaration is
typedef int (*PFI) (char *,char *)
What does it mean? What is PFI and how can we use it in our program?
Breaking it down, PFI is a pointer:
*PFI
To a function:
(*PFI)()
Which takes two arguments of type char *:
(*PFI)(char *, char *)
And returns an int:
int (*PFI)(char *, char *)
And declared as an alias of that type:
typedef int (*PFI)(char *, char *);
You could use it if you had a function that matches this pointer type, i.e:
int foo(char *x, char *y)
{
...
}
Then you can assign a pointer to the function to a variable of type PFI:
PFI f = &foo;
were you reading about pointer to functions?
If yes, then PFI is just a placeholder. It can be whatever name you give, it is just a function name. I guess it could mean "Preferred Function Interface" but that is just a guess.
so let's say you write a very crude code something like
typedef bool (*write_X_Bytes) (uint32 count, char *buffer);
then you can use it as a type in C since you used typedef in front of it like
write_X_Bytes print_line, print_word;
basically you give a prototype to user or whoever wants to use this code about parameters and return. You can checkout Linux kernel driver code for GPIO for real life usecase.
Basic rules of pointer declarations:
T *p; // p is a pointer to T
T *ap[N]; // ap is an N-element array of pointers to T
T *fp(); // fp is a function returning a pointer to T
T (*pa)[N]; // pa is a pointer to an array of T
T (*pf)(); // pf is a pointer to a function returning T
In both expressions and declarators, the subscript [] and function call () operators have higher precedence than the unary dereference * operator, so an expression or declarator like *f() is parsed as *(f()) - you are dereferencing the result of f. If you want to dereference f before calling it, you have to explicitly group the * operator with it - (*f)().
The way to read a hairy declaration is to start with the leftmost identifier and work your way out according to the rules above, applying them recursively to any function parameters.
If you have a function that uses abstract declarators in the parameter list like this one, just remember:
T * -> T *λ
T *[N] -> T *λ[N]
T (*)[N] -> T (*λ)[N]
T *() -> T *λ()
T (*)() -> T (*λ)()
where λ represents where the identifier would normally go.
So, the way to read this declaration is as
PFI -- PFI
typedef PFI -- is a typedef name for
typedef *PFI -- pointer to
typedef (*PFI) ( ) -- a function taking
typedef (*PFI) ( ) -- unnamed parameter
typedef (*PFI) ( * ) -- is a pointer to
typedef (*PFI) (char * ) -- char
typedef (*PFI) (char *, ) -- unnamed parameter
typedef (*PFI) (char *, *) -- is a pointer to
typedef (*PFI) (char *,char *) -- char
typedef int (*PFI) (char *,char *); -- returning int
In less formal terms, PFI is an alias for the type "pointer to a function taking two char * parameters and returning int".
So how would we use this?
A common use is declaring callbacks in function parameter lists:
void foo( char *foo, char *bar, PFI callback )
{
int x = callback( foo, bar );
...
}
That's a little easier to read than
void foo( char *foo, char *bar, int (*callback)(char *, char *) )
{
int x = callback( foo, bar );
...
}
It's also useful for declaring arrays or struct members:
int func1( char *x, char *y ) { ... }
int func2( char *a, char *b ) { ... }
...
struct s {
char *x;
char *y;
PFI f;
} blah = {"foo", "bar", func1};
PFI callbacks[] = { func1, func2, ... };
Again, that's a bit cleaner than writing
struct s {
char *x;
char *y;
int (*f)(char *, char *);
};
or
int (*callbacks[])(char *, char *) = { func1, func2, ... };
But...
"Being a bit cleaner" is not, by itself, sufficient reason to hide the type behind a typedef. You use a typedef to abstract away details about a type that the user of the type doesn't need to know about in order to use it.
For example, consider the FILE type in stdio.h. There is an entire API supporting the FILE type, such that you never need to know what it looks like under the hood.
In our case, however, we have to know that a PFI is a pointer to a function expecting two char * arguments and returning an int in order to use it. Using the typedef name saves a few keystrokes, but it also creates a "leaky" abstraction, since details about the type have to "leak" out to the programmer. In this case, it's honestly better to forego the typedef altogether and use the "naked" declaration.
https://cdecl.org/ says "declare PFI as pointer to function (pointer to char, pointer to char) returning int". That website didn't like the initial typedef but that makes it a type so you can you write:
PFI fp = f;
where f would have the prototype:
int f(char *, char *);
PFI just means "Pointer to a function returning int". It's a fast way to create a type that can be used quickly in code, because otherwise the syntax is complicated.
As one example, it's very useful for callback interfaces. You may want to define something like PFContext_t as a pointer to a function taking certain arguments and returning a context pointer. Then you can use the typedef in your data (if, for instance, you want to keep the pointer in a structure), and you can use the typedef in the arguments to a function called by the client, setting the callback.
I'm fairly new to C, hence could someone please help me understand the below struct declaration?
extern struct server_module* module_open (const char* module_path);
Per my understanding, module_open is pointer to the struct server_module, however, didn't understand the last part of the statement i.e. (const char* module_path)
extern struct server_module* module_open (const char* module_path); declares module_open to be a function taking a parameter named module_path of type const char * and returning a struct server-module *.
module_open is a function which returns pointer to struct server_module
and const char* module_path is input argument type. Means function takes character string as an input
extern keyword is used to tell compiler that symbol is exist in different file
For some reason I am getting the error:
expected identifier or '(' before 'wordlist'
in my header file (as well as the corresponding function definitions) for the two functions returning wordlist pointers.
With the following code:
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
typedef struct word{
char *string;
struct word* next;
}word;
typedef struct wordlist{
word *head;
word *tail;
}wordlist;
*wordlist populateList(FILE *file);
*wordlist encrypt(wordlist *wl, int rotation);
void toFile(wordlist *wl, char *outputFileName);
#endif
Can anyone tell me why this might be?
This is because when you declare a pointer, the asterisk must follow the type name, not precede it:
wordlist * populateList(FILE *file);
// ^
// |
// Here
If in populateList and encrypt you want to return a pointer to wordlist, the correct syntax is wordlist *, not *wordlist (it's exactly as it is everywhere else).
If you want to define or declare a variable you specify the type of the variable followed by the variable name. So if you want a variable of type wordlist you would use:
wordlist myVariable;
If you want to specify a variable to be a pointer to a variable type, you prefix the variable name with an asterisk so if you want a variable that is a pointer to a variable of type wordlist you would use:
wordlist *myVariable;
The reason why most experienced C programmers put the asterisk with the variable name is because of something like the following:
wordlist myVariable, *pVariable1, myVariable2, *pVariable2;
The above will create four variables. myVariable is of type wordlist. myVariable2 is of type wordlist. pVariable1 and pVariable2 are of type pointer to wordlist.
So the asterisk acts as a kind of adjective or qualifier or modifier for the variable name declaration indicating that the variable is not of the type specified but is instead a pointer to the type specified.
The combined variable definition is the same as the following four lines of definitions.
wordlist myVariable; // declares a variable of type wordlist
wordlist *pVariable1; // declares a pointer to a variable of type wordlist
wordlist myVariable2; // declares a variable of type wordlist
wordlist *pVariable2; // declares a pointer to a variable of type wordlist
Function definitions/declarations work similarly.
wordlist *myFunc (void) {
wordlist *myNew = malloc (sizeof(wordlist));
if (myNew) {
// set up myNew stuff
}
return myNew;
}
Edit: function pointers
You can also specify a variable that contains a function pointer. For instance for myFunc() above you might specify something like the following. Notice that I am using parenthesis to enforce a specific order of evaluation. What this says is that pFunc is a pointer to a function that does not accept arguments (void argument list) and which returns a pointer to a wordlist variable. There are rules about operator and modifier precedence in C however as expressions become more complicated, it is usually better to enforce an evaluation order using parenthesis. See Programs as Data: Function Pointers
wordlist *((*pFunc) (void)) = myFunc; // pointer to a function that returns a pointer to a wordlist
I am new to C, and this typedef looks a little bit strange to me. Can someone explain what it does?
typedef void (*alpm_cb_log)(alpm_loglevel_t, const char *, va_list);
It is in a header file.
You can use cdecl.org : http://cdecl.ridiculousfish.com/?q=void+%28*alpm_cb_log%29%28alpm_loglevel_t%2C+const+char+*%2C+va_list%29+
It says:
declare alpm_cb_log as pointer to function (alpm_loglevel_t, pointer to const char, va_list) returning void
in this case, it is a typedef, not a declaration.
A Simple example.
Declaration:
typedef int myint.
Use:
myint number = 7;
myint is a synonym of int.
your example
typedef void (*alpm_cb_log)(alpm_loglevel_t, const char *, va_list);
this is a pointer to a function
(*alpm_cb_log)
The arguments are
(alpm_loglevel_t, const char *, va_list)
and does not return anything.
void
The general rule with the use of typedef is to write out a declaration as if
you were declaring variables of the types that you want
It defines alpm_cb_log to be a type for a pointer to a function that takes the arguments alpm_loglevel_t, const char *, va_list and returns void.
These do look weird if you've never seen them before. It's a typedef alpm_cb_log for a pointer to a function returning void, taking two or more arguments: an alpm_loglevel_t, a const char *, and a variable argument list.
it creates the alais alpm_cb_log which is a pointer to a function that returns void and takes three paramaters. 1. a alpm_loglevel_t 2. const char *. 3 a varaibale argument list.