Calling function via pointer - c++

Here is a simple code
#include<iostream.h>
#include<stdlib.h>
#include<conio.h>
void (*func[2])(int);
void main(int n=1)
{
int i;
cout<<endl<<n;
func[0]=&exit;
func[1]=&main;
i=++n<=10;
(func[i])(n);
}
Here I am satisfied with the output (i.e. 1 to 10 in different lines). The only thing which confused me was that why the global pointer is of the type void (*ptr[2])(int). If possible, please explain in simple words that why this pointer was taken so specifically

It's not a pointer, it's an array of two pointers.
This is a function:
void func(int);
This is a pointer to a function:
void (*func)(int);
and this is an array of two pointers to functions:
void (*func[2])(int);
So func[i] points to exit if i is zero (i.e. if n is greater than 10), and points to main otherwise, where i is 1.
Note that you're not allowed to call main recursively like this, nor to give main any signature other than int main() or int main(int, char**). (At least, that's the case in modern C++; these rules presumably don't apply to the prehistoric dialect your compiler accepts).

Related

how to read this declaration int (*(*f2)(int n))[3];

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;
}

C++ function input argument by reference vs by pointer

I am new to C++ and have done only MATLAB earlier.
My Q is about the input argument of the following functions, which call variables by value,reference and pointer.
void SwapbyValue (int a, int b){
// Usual swapping code
}
void SwapbyRef (int &a, int &b){
// Usual swapping code
}
void SwapbyPoint(int *a,int *b){
//Usual swapping code
}
Since my Q isn't about how the above functions work but rather about how I call them, I've left out the code. So, I understand we call the above functions by typing SwapbyRef (i1,i2),SwapbyRef (i1,i2) and SwapbyPoint(&i1,&i2) when i1 and 12 are int.
That confuses me the life out of me. Okay, I get that the first function takes in values and makes sense. But in the second one, calling by just i1 and i2 doesn't make sense as when the function is defined, we set its input as &a and not just a but it still runs. Again in the third, we set the input argument as a pointer i.e. *a but we're passing an address &a (like 0x7956a69314d8) when we call it.
Why does it run when we pass the wrong kind of input to the function?
For example,a Matlab analogy,it looks like passing a char to a int function. Help!
int &a is a reference to an int, meaning, it will accept all int variables that already exist. What you cannot do is for example SwapbyRef(4, 5) using SwapbyRef (int &a, int &b), because 4 and 5 are temporary ints that do not exist somewhere in memory as variables.
Btw, you should probably just look up what a reference in c++ is. That would help you most, I think.

local array length is different from when it is called from a function

In the following code, std::extent<decltype(columns)>::value calculates the length of the given array. However, when the array is a function argument, the compiler behaves in different way. Could some one help me how to fix it?
output:
local array length: 5
function array length: 0
code:
#include <iostream>
#include <string>
void showcolumns_num(std::string columns[])
{
int columns_num=std::extent<decltype(columns)>::value;
std::cout<<"function array length: "<<columns_num<<std::endl;
}
int main()
{
std::string column_list[]={"col1","col2","col3","col4","col5"};
// local calculation of column number
int columns_num=std::extent<decltype(column_list)>::value;
std::cout<<"local array length: "<<columns_num<<std::endl;
// function calculation of column number
showcolumns_num(column_list);
return 0;
}
You have to pass array by reference to avoid the decay to pointer which so loses size information:
template <std::size_t N>
void showcolumns_num(std::string (&columns)[N])
Live example.
That because of the declaration:
void showcolumns_num(std::string columns[])
is the same as:
void showcolumns_num(std::string * columns)
But declaration:
std::string column_list[]={"col1","col2","col3","col4","col5"};
is the same as:
std::string column_list[5]={"col1","col2","col3","col4","col5"};
So compiler doesn't know about array size inside the function.
Just use the std::vector< std::string >.
The short answer is: Don't use arrays. Instead of string columns[N];, use vector<string> columns; or vector<string> columns(N,"");. In this answer, I'll talk a bit more about arrays, they are "interesting". But arrays are "interesting" in the way that cancer is interesting, somebody has to understand cancer, but we want to get rid of it and most people don't want to be experts.
C arrays are really weird things. They can't be passed by value, but they can be passed by reference, and C++ makes it quite easy. If you are determined - as an intellectual exercise - to pass arrays, then you can use this:
template<size_t N>
void showcolumns_num(std::string (&columns)[N])
Non-array types, like int, or struct Person, or list<vector<string>>, can be passed by value or by reference. But arrays cannot be passed by value.
If you attempt to pass an array by value, the compiler will do a trick where it will instead pass a pointer to the first element of the array. This is called pointer decay.
This means that, without warning, the compiler will rewrite your function declarations
void showcolumns_num(std::string columns[]) { // this is what you write
// changed to
void showcolumns_num(std::string* columns) { // ... but this is what you get
and every call to showcolumns_num will be changed from:
showcolumns_num(column_list); // this is what you write
// changed to
showcolumns_num(&(column_list[0])); // ... but this is what you get
The reason behind this is historical, and is related to an earlier language called B.
Variables are declared as local variables, or as global variables, or as function parameters. For local and global variables, the compiler will generally respect your wishes, but not for function parameters:
void foo(int x[5]) { // silently converted to int *x
int y[10]; // y really will be an array
}

Problems with functions parameters in pass by references in C++

I am newbie in c++ and just learning it.
I have written the following code.
#include<iostream>
#include<cstdio>
using namespace std;
void first(int &x,int n)
{
int i;
for(i=0;i<n;i++)
{
cout<<x+i;
}
cout<<endl;
}
void second(int *x,int n)
{
int i;
for(i=0;i<n;i++)
{
cout<<*x+i;
}
cout<<endl;
}
int main()
{
int exm[5]={1,2,3,4,5};
first(exm[0],5);
second(exm,5);
return 0;
}
this program gives output correctly.but the problem is i don't understand the differences between using & and * in function parameters...
both are the techniques of passing arguments by references and when we pass by reference we just send the memory address...
but in function first when i tried to call the function as follows
first(exm,5);
function occurred an error.
why ?
but when i called the function as follows
first(exm[0],5);
it compiled properly and gave right output...but i know that the both calling is equivalent...
then why this error occured?
what is the difference between using & and * in function parameters?
The type of the variable exm is int[5], which doesn't meet the signature of first(int &x,int n).
But int[N] can be converted implicitly to int* that points to the first element of the array, hence second(exm,5) can compile.
what is the difference between using & and * in function parameters?
It's the difference between a reference and a pointer.
There are lots of differences between them.
In this case, I think the biggest difference is whether it accepts NULL or not.
See:
- What are the differences between a pointer variable and a reference variable in C++?
- Are there benefits of passing by pointer over passing by reference in C++?
- difference between a pointer and reference parameter?

Returning an array ... rather a reference or pointer to an array

I am a bit confused. There are two ways to return an array from a method. The first suggests the following:
typedef int arrT[10];
arrT *func(int i);
However, how do I capture the return which is an int (*)[]?
Another way is through a reference or pointer:
int (*func(int i)[10];
or
int (&func(int i)[10];
The return types are either int (*)[] or int (&)[].
The trouble I am having is how I can assign a variable to accept the point and I continue to get errors such as:
can't convert int* to int (*)[]
Any idea what I am doing wrong or what is lacking in my knowledge?
If you want to return an array by value, put it in a structure.
The Standard committee already did that, and thus you can use std::array<int,10>.
std::array<int,10> func(int i);
std::array<int,10> x = func(77);
This makes it very straightforward to return by reference also:
std::array<int,10>& func2(int i);
std::array<int,10>& y = func2(5);
First, the information you give is incorrect.
You write,
“There are two ways to return an array from a method”
and then you give as examples of the ways
typedef int arrT[10];
arrT *func(int i);
and
int (*func(int i))[10];
(I’ve added the missing right parenthesis), where you say that this latter way, in contrast to the first, is an example of
“through a reference or pointer”
Well, these two declarations mean exactly the same, to wit:
typedef int A[10];
A* fp1( int i ) { return 0; }
int (*fp2( int i ))[10] { return 0; }
int main()
{
int (*p1)[10] = fp1( 100 );
int (*p2)[10] = fp2( 200 );
}
In both cases a pointer to the array is returned, and this pointer is typed as "pointer to array". Dereferencing that pointer yields the array itself, which decays to a pointer to itself again, but now typed as "pointer to item". It’s a pointer to the first item of the array. At the machine code level these two pointers are, in practice, exactly the same. Coming from a Pascal background that confused me for a long time, but the upshot is, since it’s generally impractical to carry the array size along in the type (which precludes dealing with arrays of different runtime sizes), most array handling code deals with the pointer-to-first-item instead of the pointer-to-the-whole-array.
I.e., normally such a low level C language like function would be declared as just
int* func()
return a pointer to the first item of an array of size established at run time.
Now, if you want to return an array by value then you have two choices:
Returning a fixed size array by value: put it in a struct.
The standard already provides a templated class that does this, std::array.
Returning a variable size array by value: use a class that deals with copying.
The standard already provides a templated class that does this, std::vector.
For example,
#include <vector>
using namespace std;
vector<int> foo() { return vector<int>( 10 ); }
int main()
{
vector<int> const v = foo();
// ...
}
This is the most general. Using std::array is more of an optimization for special cases. As a beginner, keep in mind Donald Knuth’s advice: “Premature optimization is the root of all evil.” I.e., just use std::vector unless there is a really really good reason to use std::array.
using arrT10 = int[10]; // Or you can use typedef if you want
arrT10 * func(int i)
{
arrT10 a10;
return &a10;
// int a[10];
// return a; // ERROR: can't convert int* to int (*)[]
}
This will give you a warning because func returns an address of a local variable so we should NEVER code like this but I'm sure this code can help you.