I am trying to understand a C program and here is the following lines that I don't understand them:
static A B(float* array, int numel);
static int C(D_TYPE* array, int numel);
Is variable A declared to be a scalar and B is a matrix? Why there is no "," between A and B? Is array declared as a pointer?
In the second line, the variable "D_TYPE" is appeared for the first time. I assumed that this variable is imported from the header files, but I couldn't find it inside any other included files.
The code tells that:
Somewhere (rest of the code, header file, whatever) a type 'A' is (or should be) declared. Can be anything from a custom data structure (struct) or a numeric type defined via a typedef.
B is a function (well actually a prototype of a function) that returns an 'A'. B takes a pointer to float (that by the name is implied to be an array, which in C are almost the same thing) and an integer as parameters. This is somewhat standard in C when you have to pass an array to a function.
C is a function's prototype that states that function C returns an integer. As arguments it takes a pointer to 'D_TYPE', which, again is a type that is or should be defined somewhere, and an integer.
static is used in both case probably to limit the visibility of the two functions only to the header file, which is unusual.
Personal considerations: names like 'a' or 'b' should be used only as argument values for very simple (not to say stupid) cases, like a Max(a, b) function or something similar.
In your code you have 2 function declarations, both B and C are names of functions.
The first function returns a variable of type static A and takes as arguments a float* and an int
The second one returns a variable of type static int and takes as arguments a D_TYPE* and an int, you probably have D_TYPE defined somewhere in your code or in a header file somewhere. We don't know what this D_TYPE is but it could be either a struct, a #define or a typedef, this is the same for A.
These are only the declarations of the functions, somewhere in your code you will have
static A B(float* array, int numel){
//some code
}
and
static int C(D_TYPE* array, int numel){
// some code
}
and these would be the definitions of the two functions
There isn't a , between A and B because that's just an error in C (programming language not the function), it would be the same as writing
static int , C(D_TYPE* array, int numel);
in your second declaration and this is, of course, wrong
static A B(float* array, int numel);
static is storage class, refer storage classes in c
A is a return type , that can vary from a primitive int , char to any complex struct type or even a pointer
B is name of fuction
static int C(D_TYPE* array, int numel);
here C is a function and D_TYPE is some type which might be typedefed some where in your files
You do not declare any variables here.
Both are function prototypes and A is the return type of the function B.
Related
Normally, when declaring some variable, you put its type before it, like:
int a;
a function pointer may have type like: int(*)(int,int), in case we point to a function that takes two integers and returns an integer. But, when declaring such a pointer, its identifier is not after the type, like:
int(*)(int,int) mypointer;
instead, you must write the identifier in the middle:
int(*mypointer)(int,int);
why is this so?
I explain this in my answer to Why was the C syntax for arrays, pointers, and functions designed this way?, and it basically comes down to:
the language authors preferred to make the syntax variable-centric rather than type-centric. That is, they wanted a programmer to look at the declaration and think "if I write the expression *func(arg), that'll result in an int; if I write *arg[N] I'll have a float" rather than "func must be a pointer to a function taking this and returning that".
The C entry on Wikipedia claims that:
Ritchie's idea was to declare identifiers in contexts resembling their use: "declaration reflects use".
...citing p122 of K&R2.
This structure reflects how a normal function is declared (and used).
Consider a normal function definition:
int foo (int bar, int baz, int quux);
Now consider defining a function pointer to a function of the same signature:
int (*foo) (int, int, int);
Notice how the two structures mirror each other? That makes *foo much easier to identify as a function pointer rather than as something else.
If you're dealing with a function (not a pointer to one), the name is in the middle too. It goes like: return-type function-name "(" argument-list ")" .... For example, in int foo(int), int is the return type, foo the name and int the argument list.
A pointer to a function works pretty much the same way -- return type, then name, then argument list. In this case, we have to add a * to make it a pointer, and (since the * for a pointer is prefix) a pair of parentheses to bind the * to the name instead of the return type. For example, int *foo(int) would mean a function named foo that takes an int parameter and returns a pointer to an int. To get the * bound to foo instead, we need parentheses, giving int (*foo)(int).
This gets particularly ugly when you need an array of pointers to functions. In such a case, most people find it easiest to use a typedef for the pointer type, then create an array of that type:
typedef int (*fptr)(int);
fptr array[10];
I had seen at some places function pointers declared as
int (*foo) (int a, int b);
and at some places a and b are not mentioned and both still works.
so
int (*foo) (int, int)
is also correct.
A very simple way that I found to remember is as mentioned below:
Suppose function is declared as:
int function (int a , int b);
Step1: Simply put function in parentheses:
int (function) (int a , int b);
Step2: Place a * in front of function name and change the name:
int (*funcPntr) (int a , int b);
PS: I am not following proper coding guidelines for naming convention etc. in this answer.
I am currently studying for my C-Midterm and I encountered this declaration:
int **foo[][]()
When looking for the solution as to what this declaration means my tutors actually gave two different answers:
1) foo is an array of arrays of functions with return type pointer to pointer to an int
2) foo is an array of arrays of pointers to pointers to a function with return type int
I know the "start with the name of the variable, continue to the right until you reach the end or ')' then go back to your last starting point and continue to the left until you reach the start or '('" rule so I think 1) is the correct answer here but I am not entirely sure.
Thanks,
Ozelotl
It is nothing specific. Meaning that on the surface it looks like a C declaration, but it is not well-formed. It is illegal and as such it means nothing.
Firstly, it appears like a two-dimensional array declaration, but in C language an array declaration is required to specify all sizes except possibly for the very first one. Your declaration omits the second size as well, which makes it illegal.
Secondly, even if we ignore the missing sizes, it looks like a declaration for an array of functions. It is illegal to declare arrays of functions in C.
For example, this would make a legal C declaration
int (**foo[][42])()
but not what you have originally.
The syntax of this declaration is that foo[][] declares a 2-D array (or it would, if the second bound had a dimension specified - as it stands that's illegal); and then the rest of it is:
int **bar(); // with bar = foo[][]
which is a function taking unspecified arguments and returning int **. However, since bar is an array type here this attempts to declare an array of functions, which is illegal. (Not to be confused with an array of function pointers, which would be OK).
The grammar rules are that the ** bind to the int (not to the bar) unless you use parentheses to force them to bind to the bar; so they are part of the type int ** and they are not saying that bar is a pointer.
I'm having problems understanding the syntax of a pointer to a function using typedef. I've read a lot of answers but still couldn't understand something.
I'll try to explain how I see things so you could understand my thinking.
So we use typedef to give aliases to existing types for example :
typedef int number;
Will make it so we could use a number same as an integer (similar to preprocessor directives - I know there're some differences like when making a typedef of a pointer).
Another example :
typedef struct
{
int num;
} MyStruct;
Will give the unnamed structure an alias named MyStruct.
So Here's the syntax of a pointer to function typedef:
typedef int (*pFunc)(int, int);
Maybe I'm having hard time to understand this since typedef is like it's name giving aliases to TYPES and a function is not exactly type but anyway, from my understanding this is more of a pointer to some sort of a function signature, so the first int is the returned type, the second parenthesis are to indicate what types are the arguments being passed to the function.
Now what I don't quite understand is this part :
(*pFunc)
What I think it is, is that we create a new type (using typedef)
named pFunc that is a pointer and that's the role of the *. Now we
could create variables of this type that will point to ANY function
with the signature we described. Am I correct ?
Ok, say I'm correct, usually pointers to some memory are declared as follow :
int *p;
double *p;
.
.
.
So wouldn't it make more sense to do it as follow :
(pFunc*)
Because to me it looks like if the asterisk is before the name it looks like pFunc is a variable name of type pointer of some type and not an actual type pointer.
Can we do that ^ ? If so, is it commonly used to put the asterisk
after and not before ? If it's more common to put it before then why
is that ? Because like I said when we define a pointer type we always
put the asterisk after the name itself like the examples above so why
is that exactly ?
Another question regarding to this, I don't quite understand what are
the job of the parenthesis around *pFunc.
I think that they're used to indicate that pFunc type pointer of something and if we wouldn't do put parenthesis then the return type
of the signature will be of type int* instead of just int, am I
correct here ?
Ok, another thing that bothers me about it as the order of the syntax.
So far, in all typedef definitions we had the type on the left and the alias(es) on the right.
typedef int number;
typedef struct
{
int num;
} MyStruct;
We see that the int and the struct are the types which are being on the left and the alias we gave them are on the right.
Now, in pointers to function typedef it doesn't follow this convention.
We have the type returned of the function on the right then the typename in parenthesis then the type of the arguments in parenthesis, this order makes me confused after looking on how the other typedef are working on the same order.
Wouldn't it make more sens to do something like this ? :
typedef int (int,int) Func; So we have a typedef first, the type we want to give alias(es) to, which in this case is a function
signature which takes 2 ints and return an int, and then on the right
we have the alias name. Won't it make more sense ? this follows the
other typedef order, I just don't get the function pointer order that
much ..
Another question of mine : When we make a pointer to a function, what
does it actually mean ? I understand we can call this function using
our alias but pointers like variables are stored in a memory address
? What is there to store for a function ?
Lastly, I've read that the keyword extern has something to do with
pointers to function but couldn't understand what this keyword does,
could someone explain to me what it does ?
The typedef uses the same syntax for declaring types as would normally be used for declaring values.
For instance, if we declare an int called myInt, we do:
int myInt;
If we want to declare a type called myIntType to be an int, we simply add typedef:
typedef int myIntType;
We can declare a function myFunc, as follows:
int myFunc(int a, int b);
Which tells the compiler that there is an actual function with that name and signature that we can call.
We can also declare a function type myFuncType by doing:
typedef int myFuncType(int a, int b);
And we could do:
myFuncType myFunc;
Which is equivalent to the previous declaration of myFunc (although this form would rarely be used).
A function is not a conventional value; it represents a block of code with an entry point address. Function declarations like those above are implicitly extern; they tell the compiler that the named thing exists somewhere else. However, you can take the address of a function, which is called a function pointer. A function pointer can point to any function with the correct signature. A pointer is declared by prefixing the name of the type/value with a *, so, we might try:
int *myFuncPtr(int a, int b);
But this would be incorrect because the * binds more tightly with the int, so we have declared that myFuncPtr is a function that returns a pointer to an int. We must put parens around the pointer and name to change the binding order:
int (*myFuncPtr)(int a, int b);
And to declare a type, we simply add typedef to the front:
typedef int (*myFuncPtrType)(int a, int b);
In the declaration of myInt above, the compiler allocated some memory for the variable. However, if we were writing some code in a different compilation unit, and wanted to reference myInt, we would need to declare it as extern (in the referencing compilation unit) so that we reference the same memory. Without the extern, the compiler would allocate a second myInt, which would result in a linker error (actually that's not quite true because C allows tentative definitions, which you shouldn't use).
As noted above, functions are not normal values, and are always implicitly extern. However, function pointers are normal values, and need the extern if you are trying to reference a global function pointer from a separate compilation unit.
Normally, you would put externs for your global variables (and functions) into a header file. You would then include the header into the compilation units that contain the definitions of those variables and functions so that the compiler can make sure the types match.
The syntax for a variable definition or declaration is the type followed by one or more variables possibly with modifiers. Some simple examples would be:
int a, b; // two int variables a and b
int *a, b; // pointer to an int variable a and an int variable b
int a, *b, **c; // int variable a, pointer to an int variable b, and pointer to a pointer to an int variable c
Notice that in all of these the asterisk modifies the variable to the right of the asterisk, changing it from an int into a pointer to an int or a pointer to a pointer to an int. The variables defined might be used like:
int a, *b, **c, d;
a = 5; // set a == 5
b = &a; // set b == address of a
c = &b; // set c == address of b which in this case has the address of int variable a
d = **c; // put value of a into d using pointer to point to an int variable a
d = *b; // put value of a into d using pointer to an int variable a
d = a; // put value of a into d using the variable a directly
The extern statement
The extern statement is used to indicate that the definition of a variable is located in some other file and that the variable has global visibility. So you can declare a variable using the extern keyword to be explicit about a variable so that the C compiler will have the information it needs to do a good level of checking when compiling. The extern indicates that the variable is actually defined with its memory allocation somewhere other than the file where the source using the variable is located.
Using typedef
The typedef is a very nice feature of modern C because it allows you to create an alias that amounts to a kind of halfway new type. To have the full capability of creating a new type really requires the class type features of C++ which allows the definition of operators for the new type as well. However typedef does provide a good way of allowing a programmer to create an alias for a type.
Most uses of typedef are to provide a way to make it shorter and cleaner to write a variable definition. It is used a lot with struct definitions for that reason. So you might have a struct definition like the following:
typdef struct {
int iA;
int iB;
} MyStruct, *PMyStruct;
This will create two new aliases for the struct, one for the struct itself and one for a pointer to the struct and these might be used like:
MyStruct exampleStruct;
PMyStruct pExampleStrut;
pExampleStruct = &exampleStruct;
This example has the basic structure of typedef keyword, definition of the new type in terms of existing types, and name of the new type.
Old style C before typedef
Years ago in the older C compiler days before typedef was added to the C standard, people would often use the C Preprocessor to define macros to create an alias for a complex type. typedef is a much cleaner way of doing it!
Before typedef was added to the C standard, you would specify a tag for the struct and the result would be code that looked like this:
struct myTagStruct { // create a struct declaration with the tag of myTagStruct
int a;
int b;
};
struct myTagStruct myStruct; // create a variable myStruct of the struct
At which pointer people would usually add a C Preprocessor define to make it easier to write as in:
#define MYTAGSTRUCT struct myTagStruct
and then use it something like:
MYTAGSTRUCT myStruct;
However there is one major difference between using the preferred typedef syntax rather than the Preprocessor define approach. The Preprocessor works with the text of the C source code file to generate a modified version of the C source which is then compiled by the C compiler. The typedef keyword is part of the C source compiled by the C compiler so the C compiler knows about the type alias defined.
To show the difference, see the following source code.
#define PMYSTRUCT MyStruct *
typedef struct {
int a1;
int b1;
} MyStruct, *PMyStruct;
MyStruct sA, sB; //
PMyStruct psA, psB; // compiler sees this as MyStruct *psA, *psB;
PMYSTRUCT psxA, psxB; // Preprocessor generates MyStruct * psxA, psxB;
psA = &sA;
psB = &sB;
psxA = &sA;
psxB = &sB; // compiler error - psxB is not a pointer variable
Using typedef with function pointers
The syntax of typedef for function pointers is a bit unusual. It looks somewhat like a function declaration but does have a slight twist with an additional pointer syntax.
typedef int (*pFunc)(int a1, int b1);
This says the following:
create a typedef for a variable type pFunc
a variable defined as a pFunc type is a pointer
what the variable points to is a function with two int arguments that returns an int
The parenthesizes are important because they force the compiler to interpret the source text in a way different from the default rules. The C compiler has rules that it uses to parse the source text and you can change the way that the C compiler interprets the source text by using parenthesizes. The rules have to do with the parsing and how the C compiler locates the variable name and then determines the type of the variable by using rules about left and right associativity.
a = 5 * b + 1; // 5 times b then add 1
a = 5 * (b + 1); // 5 times the sum of b and 1
int *pFunc(int a1, int b1); // function prototype for function pFunc which returns a pointer to an int
int **pFunct(int a1, int b1); // function prototype for function pFunc which returns a pointer to a pointer to an int
int (*pfunc)(int a1, int b1); // function pointer variable for pointer to a function which returns an int
int *(*pFunc)(int a1, int b1); // function pointer variable for pointer to a function which returns a pointer to an int
A function prototype is not a function pointer variable. The syntax of a typedef is similar to the syntax for a variable definition that is not using a typedef.
typedef int * pInt; // create typedef for pointer to an int
int *a; // create a variable that is a pointer to an int
pInt b; // create a variable that is a pointer to an int
typedef int (*pIntFunc)(int a1, int b1); // create typedef for pointer to a function
typedef int *pFuncWhat(int a1, int b1); // create a typedef for a function that returns a pointer to an int. seems to be legal but useful? doubt it.
int (*pFuncA)(int a1, int b1); // create a variable pFuncA that is a pointer to a function
int *FuncDecl(int a1, int b1); // declare a function that returns a pointer to an int
pIntFunc pFuncB; // create a variable pFuncB that is a pointer to a function
So what does it mean to have a pointer to a function? A function entry point has an address because a function is machine code that is located at a particular memory area. The address of the function is where the execution of the functions machine code is supposed to start.
When the C source code is compiled, a function call is translated into a series of machine instructions which jump to the address of the function. The actual machine instructions are not really a jump but are instead a call instruction which saves the return address before it makes the jump so that when the called function completes it can do a return back to where it was called from.
A function pointer variable is used like a function statement. The difference between the two is similar to the difference between an array variable and a pointer variable. An array variable is treated like a constant pointer to a variable by most C compilers. A function name is treated like a constant pointer to a function by most C compilers.
Using a function pointer
What a function pointer does give you though is flexibility though it is flexibility that as with any great power can also lead to great ruin.
One use of function pointer variables is to pass a function address as an argument to another function. For instance the C Standard library has a couple of sort functions that require an argument of a collation function for comparing two elements being sorted. Another example would be a threading library that when you create a thread, you specify the address of the function to be executed as a thread.
Since a function pointer is a variable then if you have a function pointer that needs global visibility when you declare the variable for files other than the source file where it is actually defined and its memory allocated you would use the extern keyword as part of the function pointer variable declaration. However if it is a variable that is allocated on the stack within a function or if it is used within a struct to create a member of the struct then you would not use the extern modifier on the variable.
file1.c
// define a function that we are going to make available
// through a function pointer. a function will have global
// visibility unless we use the static keyword to reduce the
// visibility to this source file.
static int myfunc(int a, float b)
{
return (a + (int) (b * 100.0));
}
// define a function pointer that contains the address of the
// function above that we are exporting from this file.
// this function pointer variable automatically has global visibility
// due to where the statement is located in the source file.
int(*pmyfunc)(int, float) = myfunc;
file1.h
// declare the function pointer, which has global visibility
// due to where it was defined in the source file. we declare
// the function pointer in an extern in order to make the
// function prototype with argument types available to the compiler
// when using this variable in other source files.
extern int(*pmyfunc)(int, float);
file 2.c
#include "file1.h"
int iifunc (int a, int b)
{
return (a + b/10 + 5);
}
// define a function that has as an argument a function pointer
// variable. this allows the caller to inject into the processing
// of this function a function to be used in the function.
int jjfunc (int a, int (*pf)(int, float))
{
return ((a / 10) + pf(a, 2000.0));
}
int kkfunc (int a, char *pName)
{
// an example of a local definition of a function pointer.
// we could have used pmyfunc directly.
int(*plocalfunc)(int, float) = pmyfunc;
// following two statements show difference between calling a
// function with a function pointer argument and calling a
// function with a function call in the argument list.
int k = jjfunc(a, plocalfunc);
int l = iifunc(a, pmyfunc(a, 3000.0));
printf ("%s - %d\n", pName, k);
return k;
}
Another case is to provide some kind of interface that hides implementation details. Let's say that you have a print function that you want to use for several different output sinks or places where the output to go, say a file, a printer, and a terminal window. This is similar in nature to how virtual functions are implemented by C++ compilers or how COM objects are implemented through a COM interface. So you could do something like the following which is a very simple example missing details:
typedef struct {
int (*pOpenSink) (void);
int (*pPrintLine) (char *aszLine);
int (*pCloseSink) (void);
} DeviceOpsStruct;
DeviceOpsStruct DeviceOps [] = {
{PrinterOpen, PrinterLine, PrinterClose},
{FileOpen, FileLine, FileClose},
{TermOpen, TermLine, TermClose}
};
int OpenDevice (int iDev)
{
return DeviceOps[iDev].pOpenSink();
}
int LineDevice (int iDev, char *aszLine)
{
return DeviceOps[iDev].pPrintLine (aszLine);
}
int CloseDevice (int iDev)
{
return DeviceOps[iDev].pCloseSink();
}
Just to make clear the explanation given by others, in C/C++, the parenthesis are right associative, therefore the following declaration:
typedef int *pFunc(int, int);
is equivalent to:
typedef int *(pFunc(int, int));
which would be the declaration prototype of a function returning a pointer to an integer and not the declaration of a pointer to a function returning an integer.
This is why you need to write the parenthesis around (*pFunc) to break the right association and tell the compiler that pFunc is a pointer to a function and not simply a function.
I'm reading this C BNF grammar. I have the following questions:
Is correct which it's <declarator> job to parse this syntax: id(int a, int b) (in <direct-declarator>) and so on to arrays in parameters of a function prototype/definition, etc;
In <function-definition>, why is <declarator> followed by a {<declaration>}* ?
from what I understood, it could make valid a type name or storage class followed by a function header like id(int a, int b) int. But I'm sure it isn't valid in C. What am I missing?
Yes, <declarator> in that grammar is the name of the object being declared, plus its arguments or array size (and also the pointer qualifiers of its type). <declarator> does not include the base type (return type for a function; element type for an array).
Note that there are two alternatives in <direct-declarator>, both of which seem relevant to functions:
<direct-declarator> ( <parameter-type-list> )
<direct-declarator> ( {<identifier>}* )
The first of these is what we normally think of as a function declaration, where the parameters are types or types-with-parameter-name. The second one is just a list of identifiers. (It should, I think, be a comma-separated list of identifiers.) The second case is the old-style "K&R" function definition syntax, which you may never have seen before, and should immediately forget about after reading this answer because -- while C compilers still accept it -- it has been deprecated for not just years, but decades. So don't use it. For historical completeness, here's how it looked:
int foo(n, p)
int n;
char p;
{
/ Body of the function */
}
Just started with K & R and on the 2nd chapter, there is the line:
Declarations list the variables to be
used and state what type they have and
perhaps what their initial values are.
So:
int x = 42 is a definition.
and int x is a declaration but also a definition since every definition is a declaration.
But when we assign an intial value like K & R say, doesn't that make the declaration a definition?
You confuse two things:
A declaration states (declares) what an object's* type, name and scope is
A definition defines what a object's content is
* object as in: variable, function etc., not an OOP object.
A definition is hence very often also a declaration, since you cannot define what is in an object when you do not state what the type of the object is. Easiest to remember is just: "Every definition is a declaration, but not every declaration is a definition"
For variables
There is only 1 way to declare without defining the variable:
extern typeX variable_name
This tells the compiler that there is a variable called variable_name with type typeX, but not where to get it.
Every other way to declare a variable is also a definition, since it tells the compiler to reserve space for it and perhaps give it an initial value.
The difference is much clearer in structs and functions:
For Structs
A declaration:
struct some_struct{
int a;
int b;
}
This declares some_struct to the compiler with a and b as struct variables both with type int.
Only when you define them space is reserved and you can use them:
void foo(){
struct some_struct s;
s.a = 1; // For this to work s needs to be defined
}
For functions:
The difference is much more clear
declaration:
// This tells the compiler that there is a function called "foo" that returns void and takes void arguments
void foo();
A definition could be like the one above (in the struct part)
Basically you can say that a declaration simply tells the compiler that there is somewhere a variable with that name and type. It does produce any code, and in C, this has to be done with the extern keyword on variables. Function prototypes (without implementation) are also mere declarations, and don't need the extern keyword, but you can still provide it.
A definition produces code, e.g. allocates memory on the stack or heap for a variable, or the body for methods.
In that sense, both of your statments are definitions, and any definition is also a delcaration.
I think that might by a mistake by K&R...