Can somebody explain me the difference between the following?
Those two
float *pointer[10];
float *(pointer[10]);
and those two
int(*pointer_function)();
int *pointer_function();
These two declarations
float *pointer[10];
float *(pointer[10]);
are equivalent. You can write even the following way
float *( ( pointer )[10] );
That is it is a declaration of an array of 10 pointers to float.
These declarations
int(*pointer_function)();
int *pointer_function();
are different. The first one declares a pointer to a function of type int(). The second one declares a function (not a pointer to a function) with type int *().
Here is a demonstrative program
#include <iostream>
int * pointer_function() // #1
{
static int x = 1'000'000;
return &x;
};
int f1() // #2
{
return 2'000'000;
}
int main()
{
std::cout << *pointer_function() /* calling #1 */<< '\n';
int( *pointer_function )() = f1;
std::cout << pointer_function() /* calling #2 */ << '\n';
return 0;
}
Its output is
1000000
2000000
To make more obvious the difference between the declarations you can rewrite the second declaration (that is the declaration of function) the following way
int * ( pointer_function )();
Compare it with the pointer to function declaration
int ( *pointer_function )();
Take into account that a declarator may be enclosed in parentheses.
Always keep in mind the place of Parentheses. Parentheses do not alter the type of the object, but they can alter the binding of complex declarators.
From above code snippet:
float *pointer[10];// Array of 10 pointer to float
float *(pointer[10]); //bracket around array of 10 pointer to float, So same as above
int(*pointer_function)(); // function pointer to achieve callbacks
int * pointer_function(); // function to integer pointer
Related
I got this declaration from https://en.cppreference.com/w/cpp/language/scope, but don't know how to parse this declaration even there is a comment below.
my questions is
how to parse the declaration statement (I see it as a function pointer to a function protocol like "int[3] foo(int n)" or "int foo(int n)[3] --- they are illegal in C++ )? Then, how can I construct a concrete function which can be assigned to this function pointer? Thanks.
const int n = 3;
int (*(*f2)(int n))[n]; // OK: the scope of the function parameter 'n'
// ends at the end of its function declarator
// in the array declarator, global n is in scope
// (this declares a pointer to function returning a pointer to an array of 3 int
It's a pointer to a function taking an int and returning a pointer to an int array of size three.
All the comment is saying is that there are two n identifiers in play here. The [n] (in array declarator) is using the const int 3, not the parameter to the function (which is in the function declarator).
Starting in the middle, with each segment being included in the subsequent bullet point as ...:
f2 is a pointer, (*f2).
It's a pointer to a function taking an integer, ...(int).
It returns a pointer to an int array of size three, int (*...)[3].
You can form a concrete function for it as per the following complete program, which output the first element, 42:
#include <iostream>
const int n = 3;
int (*(*f2)(int n))[n];
int (*g2(int))[n] {
static int x[::n] = { 42 }; // Use outer n, not the parameter.
return &x; // since C++ has no VLAs. This
// means parameter is not actually
// needed in this test case, though
// it may be in more complicated
// tests.
}
int main() {
f2 = &g2; // Assign concrete function to pointer.
auto y = f2(3); // Call via pointer, get array.
std::cout << *(y[0]) << '\n'; // Deref first element to get 42.
}
Having said that, I would be rather curious if one of my colleagues submitting something like that for a code review, at least without a large comment explaining it. Although seasoned developers may be able to work it out, those less experienced may have trouble.
And, in fact, even seasoned developers shouldn't have to work it out, especially given it took me a few minutes.
C++ has a very expressive type system which can easily build something like this up in parts, so you don't have to experience migraines trying to work it out. For something like this, I'd be using std::vector (or std::array) unless there was a compelling case for the added complexity caused by more basic types.
You can create a type for pointer to an array of 3 int
typedef int (*array_with_size_n)[n];
and then use it as return type
const int n = 3;
int (*(*f2)(int n))[n];
int arr[n];
array_with_size_n func(int n)
{
return &arr;
}
int main()
{
f2 = &func;
return 0;
}
I wrote the piece of code below but when I tried to return some two-dimensional array, it throws the following error.
int (* function (int input[2][2]) ) [2][2]{
return input;
}
from trial and error, I understand that when I change the function declaration to int (* function (args) ) [2] {...} it works like a charm, but why??? I don't understand. How C++ actually sees arrays? How these return declarations int (* function () )[n][m] actually works? What happens when I add another * to function declaration int *(* function () )[n][m] ??
My source for finding the solution to this problem was this but I just copied some code and understood almost 0% of it.
It'll be nice if someone could explain to me how these work, and it would mean a world to me if you can suggest a good reading source for understanding these somewhat advanced notions in C++.
In this function declaration
int (* function (int input[2][2]) ) [2][2];
the argument of the array type is implicitly adjusted by the compiler to pointer to the array element type. That is for example these function declarations
int (* function (int input[2][2]) ) [2][2];
int (* function (int input[100][2]) ) [2][2];
int (* function (int input[][2]) ) [2][2];
declares the same one function that is equivalent to
int (* function (int ( *input )[2]) ) [2][2];
So within the function the variable input has the pointer type int ( * )[2]. This pointer you are returning from the function
return input;
So the function return type also must be int ( * )[2]. That means that the function must be declared like
int (* function (int input[2][2]) ) [2];
You could declare the parameter as having a referenced type. In this case you may return reference to the array.
int ( & function (int ( &input )[2][2]) )[2] [2];
Array types may not be used as the return type of function.
As for this declaration
int *(* function () )[n][m];
where n and m shall be constant expressions then the function returns pointer of the type int * ( * )[n][m]. For example the function can use an array name declared within the function with the static storage duration something in a return statement like
static int * a[k][n][m];
//
return a;
So if you have an array as for example
T a[N1][N2][N3];
where T is some type and N1, N2, and N3 its sizes then this declaration you may rewrite like
T ( a[N1] )[N2][N3];
Used in expressions the array (with rare exceptions) is converted to pointer to its first element. To declare such a pointer substitute the record in the parentheses to pointer like
T ( *p )[N2][N3] = a;
I am getting 3 errors:
line 12:-invalid conversion from int* to int
line 17:-x was not declared in this scope
line 16:- expected primary expression before',' token
Please help me to fix this. Here is the code:
#include<iostream>
int power(int x[5])
{
x[0]=12;
x[1]=23;
x[2]=234;
x[3]=344;
x[4]=232;
return x;
}
int main()
{
int action[5]={1,2,3,,4,5};
std::cout<<x[0]<<std::endl;
x();
std::cout<<x[0]<<std::endl;
return 0;
}
your help would be appreciated!
First of all, the errors are pretty self explanatory.
invalid conversion from int* to int
Your function is declared in such a way it is expected to return an int. Not an array of ints, just an int. Furthermore, you cannot return an array from a function. You can, however, return a pointer to the first element, which in your case is unnecessary.
Guessing that you want your function to simply set values in an array, you can achieve that by declaring the function as void returning:
void power(int x[5])
{
x[0]=12;
x[1]=23;
x[2]=234;
x[3]=344;
x[4]=232;
}
x was not declared in this scope
Well, given your main:
int main()
{
int action[5]={1,2,3,,4,5};
std::cout<<x[0]<<std::endl;
// ^
...
}
Here you attempt to use a variable x, which was never declared inside main or as global variable, thus the compiler has no idea what you are referring to. Simply aliasing an argument as x in some unrelated function won't make it visible to all the code. Your can't use it like this.
expected primary expression before',' token
Take a close look at your main function and at action declaration. The part:
int action[5]={1,2,3,,4,5};
// ^^
is illegal. Notice the ,,. You either should put an integer inbetween them, or delete one of them.
What you probably wanted to achieve, was to first declare the array, print out the first element, apply the power() function and print the first element again, hoping it to change. Given the declaration of power() that I have written, you could achieve it by doing it like so:
#include <iostream>
void power(int x[5])
{
x[0]=12;
x[1]=23;
x[2]=234;
x[3]=344;
x[4]=232;
}
int main()
{
int x[5] = {1,2,3,4,5};
std::cout << x[0] << ' ';
power(x);
std::cout << x[0] << std::endl;
}
That outputs: 1 12.
The first error is a simple mis-declaration: The function receives a pointer and returns a pointer, so the return type is int *, not simply int. By the way, I like it that the function returns the pointer because it allows for function nesting like in the code below (the result of a function call can be the direct argument for another).
Note that the parameter x you declare is a pointer, despite appearances. One can declare a pointer parameter in two ways:
f ( int *p );
or
f2( int p[] );
The two are completely identical; it is impossible to pass arrays to functions. They always are "adjusted" to pointers to the first element.
In fact, one could even write
f2( int p[100] );
which I demonstrate in the code below. The number is irrelevant and ignored. In particular, the compiler does not think there is an array, and it does no type or index checking of the actual arguments.
Now the original function you present is unsafe; it's entirely up to the caller to provide an array with 5 elements.
C++ has the possibility to pass references, and even true references to arrays. Arrays of different sizes have different types, even if the elements are of the same type. This makes normal functions taking references to arrays pretty useless (unless you have an application like a screen buffer where all arrays are of the same size, known at coding time).
But C++ has also templates, which are a facility to construct functions at compile time from a provided pattern, depending on type and int parameters provided by the caller at compile time (but not necessarily at template coding time!). For functions these template parameters can be inferred by the compiler from the function arguments which makes template functions handy to use: The compiler creates the proper one almost magically.
A function iterating over all elements of a fixed-size array is a prime candidate for a template. Check out the last function in the code below.
#include<iostream>
using namespace std; // for brevity in the example
/** An unsafe function based on passing pointers
without element counts.
*/
int *power_5_elems(int x[100]) {
// This is somewhat scary.
// There is no way to check whether the array
// starting at x has indeed 5 elements. It's
// like writing assembler: All is up to the caller.
// Another thing: It would be nice to use a loop.
// We know there are 5 elements, right?
x[0] = x[0] * x[0];
x[1] = x[1] * x[1];
x[2] = x[2] * x[2];
x[3] = x[3] * x[3];
x[4] = x[4] * x[4];
return x;
}
// A reference to an int array with 5 elements.
// Remember, a typedef is written like a variable declaration; the
// type name takes the syntactic place of the variable.
// To decipher it, solve the expression in the parentheses first:
// "I must first de-reference the variable".
// The next operator is the square brackets index operator:
// "I must index the result of the dereferencing" (i.e. it is an array).
// There are 5 indices (0..4).
// The last information is: "The resulting type is int."
// Summed up: This is a reference to an array with 5 elements of type int.
typedef int(&intArr5)[5];
/** This is a nicer way to declare the function below. */
intArr5 power_ref5Arr(intArr5 arrRef);
/** A safe function with very limited usability.
It works only for int arrays with 5 elements.
This is the raw declaration of the same function.
*/
int (&power_ref5Arr( int (&x)[5] ))[5] {
// This is not scary at all.
// Only arrays with 5 ints can be supplied.
for (int i = 0; i < 5; i++)
{
x[i] = x[i] * x[i];
}
return x;
}
/** A versatile function which squares arrays
of arbitrary length of any type that isn't on
a tree on the count of three. It's very similar to the
function above with 5 int elements.
*/
template<int N, typename T>
T(&refPower( T (&arr)[N] ))[N]
{
// Note the use of the template parameter N
// in place of the "5" above.
for (int i = 0; i < N; i++)
{
arr[i] = arr[i] * arr[i];
}
return arr;
}
int main() {
int x[5] = { 2,3,4,5,6 };
int *p = &x[0]; // make clear: this is a pointer
power_5_elems(power_5_elems(power_5_elems(x)));
cout << x[0] << endl;
// The function actually expects a pointer!
// The pointer points to x.
power_5_elems(p);
cout << x[0] << endl;
int y[2] = { 2,3 };
refPower(refPower(refPower(y)));
cout << y[0] << endl;
double z[2] = { 0.2 , 0.3 };
refPower(refPower(refPower(z)));
cout << z[0] << endl;
return 0;
}
How to interpret the following c++ declaration?
int (*(*x[2])())[3];
This is from the example present at Type-cppreference.
The interpretation of the sample declaration in the question is present in the Type-cppreference page linked.
int (*(*x[2])())[3]; // declaration of an array of 2 pointers to functions
// returning pointer to array of 3 int
So the actual question is not about that case in particular; but about how any C++ declaration shall be read.
You can infer all those details starting at the declared name x and moving clockwise respecting parenthesis. You will get to the description above:
x is a an array of dimension 2 of pointers to functions that return a pointer to an array of dimension 3 of ints.
Better explained here as the Clockwise/Spiral Rule: http://c-faq.com/decl/spiral.anderson.html
It is an array of two pointers to functions that return pointer to array of type int[3] and do not have parameters.
Here is a demonstrative program
int ( *f() )[3] { return new int[2][3]; }
int ( *g() )[3] { return new int[4][3]; }
int main()
{
int (*(*x[2])())[3] = { f, g };
for ( auto func : x ) delete []func();
return 0;
}
Im a little bit confused about passing structs into functions. I understand pointers and everything.
But for instance:
struct stuff
{
int one
int two
};
int main{
stuff fnc;
fnc.two = 2;
fnc.one = 1;
multiply(&fnc);
}
void multiply(const stuff * pm){
cout << pm->one * pm->two;
}
First of all....am i even doing this right.
And second of all, why do we use the address operator when we pass the function, but use the * pointer operator in the actual function call?
Im confused?
Yes, your code is compilable other than the missing semicolons in the defintion of struct stuff. I'm not quite sure exactly what you're asking about passing the function and the actual function call, but I think you're wondering why the function call uses &fnc, but the parameter is stuff *pm? In that case, the fnc variable declared is a plain stuff. It is not a pointer, it refers to the actual instance of that struct.
Now the multiply function is declared as taking a stuff* -- a pointer to a stuff. This means that you can't pass fnc directly -- it's a stuff and multiply expects a *stuff. However, you can pass fnc as a stuff* by using the & operator to take the address, and &fnc is a valid stuff* that can be passed to multiply.
Once you're in the multiply function, you now have a stuff* called pm. To get the one and two variables from this stuff*, you use the pointer to member operator (->) since they are pointers to a stuff and not a plain stuff. After obtaining those values (pm->one and pm->two), the code then multiples them together before printing them out (pm->one * pm->two).
The * and & operands mean different things depending on whether they describe the type or describe the variable:
int x; // x is an integer
int* y = &x; // y is a pointer that stores the address of x
int& z = x; // z is a reference to x
int a = *y; // a in an integer whose value is the deference of y
Your pm variable is declared as a pointer, so the stuff type is modified with *. Your fnc variable is being used (namely for its address), and thus the variable itself is marked with &.
You can imagine the above examples as the following (C++ doesn't actually have these, so don't go looking for them):
int x;
pointer<int> y = addressof(x);
reference<int> z = x;
int a = dereference(y);
It the difference between describing a type and performing an operation.
In
void multiply(const stuff * pm){
cout << pm->one * pm->two;
}
The stuff * pm says that pm is an address of a stuff struct.
The
&fnc
says "the address of fnc".
When a variable is declared like:
stuff *pm;
it tells us that pm should be treated like an address whose underlying type is stuff.
And if we want to get the address of a variable stuff fnc, we must use
&fnc
You need the address of operator so you can get the address of the object, creating a pointer, which the function expects. The '*' in the parameter list is not a pointer operator, it simply says that the variable is a pointer.
Your code is correct. In the main, you successfully create a 'stuff' object and set its values. Then, you pass a constant address to the object into the function multiply. The multiply function then uses that address to access the two variables of the structure to output the multiplication of the variables.
The * in "const stuff * pm" means that it takes a constant pointer to a stuff object.
Here is a working example of what you would like to see.
#include <iostream>
using namespace std;
struct stuff
{
int one;
int two;
};
void multiply(stuff* pm)
{
cout << pm->one * pm->two;
}
int main()
{
stuff* fnc = new stuff;
fnc->two = 1;
fnc->one = 2;
multiply(fnc);
delete fnc;
cin.ignore(1000, 10);
return 0;
}
Sure, this would work, aside from your erroneous main function definition.
The reason why this works is because when you use the unary & operator, it essentially returns a pointer to the operand, so in your case, fnc, which is of type stuff, if you did &fnc, that would return a stuff *. This is why the multiply function must take in a stuff *.
struct stuff
{
int one, two;
};
int main(int argc, const char* argv[]) {
stuff fnc;
fnc.two = 2;
fnc.one = 1;
multiply(&fnc); //passes a pointer to fnc
}
void multiply(const stuff * pm){
//the "*" operator is the multiplication operator, not a pointer dereference
cout << pm->one * pm->two; //->one is equivalent to (*pm).one
}
You have a couple of syntactic errors in your program, but other than that, the basic idea is fine. Here are the syntax problems I had to fix before your program would compile:
#include <iostream>
using namespace std;
struct stuff
{
int one;
int two;
};
void multiply(const stuff * pm) {
cout << pm->one * pm->two;
}
int main() {
stuff fnc;
fnc.two = 2;
fnc.one = 1;
multiply(&fnc);
}
To answer your questions about difference between the '&' (address of) operator and the '*' (pointer dereference) operator though, we just need to think about the types you're passing in to the function.
Take the function multiply:
void multiply(stuff *fnc) {
...
}
In the definition of this function, you are describing something that takes a pointer to a stuff struct. In that first line, you aren't saying you are dereferencing that object, just that you are expecting a pointer to a stuff object.
Now when you call multiply:
stuff fnc;
multiply(&fnc);
You are using the '&' (address of) operator to get a pointer to the object. Since the multiply function expects a pointer, and you have the plain old object, you need to use the & operator to get a pointer to give to the multiply function.
Perhaps it is clearer to think call it like this:
stuff fnc; //The actual object
stuff* fnc_ptr = &fnc; //A pointer to a stuff object, initialized to point at fnc created above
multiply(fnc_ptr); //Call the function with the pointer directly
Following code will tell you about the pointer illustration
A struct address is passed into the function named multiply and this
function perform some operations with the element of the passed
structure and store the result in the result variable.
you can see here clearly that the result variable is previously zero then after passing the address of the structure to the function multiply the result variable value gets updated to value 6. this is how pointer works.
#include <iostream.h>
struct stuff
{
int one;
int two ;
int result;
};
void multiply(stuff *pm);
int main(){
stuff fnc;
fnc.two = 2;
fnc.one = 3;
fnc.result = 0;
multiply(&fnc);
cout<<fnc.result;
return 0;
}
void multiply(stuff *pm)
{
pm->result = pm->one * pm->two;
}