Difference in results when calling inside void function C++ - c++

Why is there a difference in the results when I call an array inside a void function and when I call a scalar inside a void function:
Pass an array into a void function:
#include <iostream>
const int n_cells = 1;
using namespace std;
void function1(int c[n_cells], int a, int b)
{
c[0] = a + b;
}
int main(){
int a = 3;
int b = 4;
int c[n_cells];
function1(c, a, b);
cout<<"c = "<<c[0];
return 1;
}
Result:
c = 7
Pass a scalar into a void function
#include <iostream>
using namespace std;
void function1(int c, int a, int b)
{
c = a + b;
}
int main(){
int a = 3;
int b = 4;
int c;
function1(c, a, b);
cout<<"c = "<<c;
return 1;
}
Result:
c = 2130567168 //Some trash value
P.S. Any comments on why I receive the same trash value as given above every single time?

void function1(int c[n_cells], int a, int b)
effectively passes a pointer to the caller's array. function1 then operates on the caller's array meaning that any updates are available to the caller.
void function1(int c, int a, int b)
passes a copy of c. It does not have access to the caller's variable so cannot update it. main never assigned c so you print out an uninitialised value.
If you want to update an integer argument, you can pass it by reference instead
void function1(int& c, int a, int b)
// ^
Rather than passing a copy of the caller's c, this now passes a pointer to the caller's variable, allowing function1 to update it.

The array parameter is actually transformed to the type int*, so what you're actually doing is passing a pointer to the first element of the array declared in main. So when you assign to the first element of this array, you are modifying the array in main.
However, when you pass an int, the int is copied into the function and you modify that copy. This modification will not be seen in main.

You could get the same result in the second program if you would define the function the following way
void function1(int *c, int a, int b)
{
c[0] = a + b;
}
When you pass an array by value it is converted implicitly by the compiler to pointer to its first element. So these function declarations are equivalent and declare the same function
void function1(int c[n_cells], int a, int b);
void function1(int c[10], int a, int b);
void function1(int c[], int a, int b);
void function1(int *c, int a, int b);
Compare the last declaration with the declaration I showed you for the second program.
In the second program the function gets a copy of its argument. Its parameter is a local variable of the function. So any changes of this local variable will be discarded after exiting the function that is the local variable will be destroyed.
In the first program the function gets the address of the first element of the array. It makes changes at this address. So the corresponding element of the original array will be changed.

Related

Calling a void function to another void function BEFORE calling to the main function

Please bear with me as I am brand new to coding.
I am trying to figure out how to call a void function to another void function. Here is what I came up with:
#include <iostream>
using namespace std;
void test(int x,int n, double &test1);
void ref(int a,int b, double &ref1);
int main()
{
int x,n;
double test1;
cout<<"Enter x and n: ";
cin>>x>>n;
test(x,n,test1);
cout<<"Your value is "<<test1;
return 0;
}
void test(int x,int n, double &test1)
{
int a, b,ref1;
ref(a,b,ref1);
test1=x+n + ref1;
}
void ref(int a,int b, double &ref1)
{
ref1=a+b;
}
But I am getting an error:
main.cpp: In function 'void test(int, int, double&)':
main.cpp:32:17: error: cannot bind non-const lvalue reference of type 'double&' to an rvalue of type 'double'
32 | ref(a,b,ref1);
| ^~~~
main.cpp:14:31: note: initializing argument 3 of 'void ref(int, int, double&)'
14 | void ref(int a,int b, double &ref1);
| ~~~~~~~~^~~~
I am trying to use the void ref function inside the void test function and print out under the main function. Can I do this?
Your ref() function takes a non-const reference to a double in its 3rd parameter. However, your test() function is initializing that parameter with an int variable. So, the compiler has to perform an implicit conversion from int to a temporary double, but then fails because a non-const reference can't bind to a temporary object, hence the compiler error.
You need to change test() to pass a double variable to ref() (just like main() is doing when calling test()), eg:
void test(int x,int n, double &test1)
{
int a, b;
double ref1; // <-- here
ref(a,b,ref1);
test1=x+n + ref1;
}
Also note that test() is not initializing its a or b variables with any values, but is still passing them to ref(), which will then sum their values together and assign the result to ref1. That summation will have undefined behavior, and the resulting value of ref1 will be indeterminate. You need to fix that, too.

Passing a member function as arguments using pointer-to-member-function C++

I am trying to pass a member function as argument using pointer-to-member-function. I have already seen some links like this here but I could not solve the problem.
The class Foo has two member functions. I need to pass the addition function as an argument to the NewOper function.
This is my code. I can correctly use pointer to call the addition function but it gives me an error when I try to pass it as an argument to NewOper function. I appreciate it if you tell me how I can fix it. (The last two lines cause error)
#include <iostream>
using namespace std;
class Foo{
public:
int addition(int a, int b)
{
return (a + b);
}
int NewOper(int x, int y, int(*fnc2call)(int, int))
{
int r;
r = (*fnc2call)(x, y);
return (r);
}
};
int main()
{
int m,n, k, l;
int (Foo::*fptr) (int, int) = &Foo::addition;
Foo obj;
m=(obj.*fptr)(1,2);
Foo* p = &obj;
n=(p->*fptr)(3,4);
cout << m << endl;
cout << n << endl;
//**********************
int (Foo::*fptr) (int, int, int(*fnc2call)) = &Foo::NewOper;
k = (obj.*fptr)(1, 2, addition);
}
You already have answer in your own code:
int (Foo::*fptr) (int, int) = &Foo::addition - here you correctly declared fptr as pointer to function, which is (non static) member of class Foo
But you forgot to do the same in you NewOper function definition:
int NewOper(int x, int y, int(*fnc2call)(int, int)) - this function wants address of free function as 3rd argument. Redefine it in the same way you declared fptr. But then you'll need to pass also pointer to an object of class Foo to this function
Alternatively, you can make your function addition function static as Jarod42 suggested (actually, the way it is written now, there is no reason for it to be member of class Foo unless you have further plan on it). Then you'll need to remove Foo:: from fptr definition

call by reference in functions

I am practicing functions in C++. In some random notes, I found an example of functions call by value and call by reference.
The code is
#include <string.h>
#include <iostream>
#include<stdio.h>
using namespace std;
void F1(float a, float b)
{
a++;b++;
}
void F2 (float &a, float &b)
{
a++;
b++;
}
int main ()
{
float a=9,b=5;
float *ptrA=&a;
float *ptrB=&b;
F1(a,b);
cout<<"\na:"<<a<<"\nb:"<<b;
F2(a,b);
cout<<"\na:"<<a<<"\nb:"<<b;
}
Now for the function F2, I am confused that in the main function I have passed the value of a and b and in the definition it received the address of the variable a and b. Then how will the increment be done in the values of a and b?
The call
F2(a,b);
Actually sends the addresses of a and b, and not their values, because of the way F2 is declared. In C++, references are like pointers, just with a cleaner syntax. So F2 actually gets the addresses of a and b, and then a++ and b++ operate on the original variables defined in main().
It looks like you're after passing a float pointer to the function
void F1(float a, float b)
{
a++;b++;
}
void F2 (float* a, float* b)
{
a++;
b++;
}
int main()
{
float a, b;
a = 5;
b = 7;
F1(a, b);
// a is still 5 and b 7
F2(&a, &b);
// a is 6 b is 8
}

What is wrong with this simple code with vectors?

The following code is one that I written for myself in order to test how pointers and vectors work.
I am very new to C++.
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
//Create the integer pointer vector, and clean it to initialize
vector<int *> lol;
lol.clear();
//Create the pointers and point them to 1,2,3
int a1=1, a2=2, a3=3;
int* a, b, c;
a=&a1;
b=&a2;
c=&a3;
//Put the pointers into the vector
lol.push_back(a);
lol.push_back(b);
lol.push_back(c);
//Return the value of the middle pointer
cout << *lol[1];
}
I get a whole wall of errors while compiling.
Can anyone help? Bear in mind I can only understand novice.
The problem is with this line:
int* a, b, c;
a is int*, but b and c are just ints.
int *a, *b, *c;
Would make it all int*s.
int* a;
int* b
int* c;
does the same thing, but with clearer intentions of declaring three int*s.
See: Placement of the asterisk in pointer declarations
UPDATE: Even better:
int* a = &a1;
int* b = &a2;
int* c = &a3;
Whenever you can, don't separate variable initialization and its declaration.
When declaring multiple pointers on one line, you have to specify the * symbol in front of each pointer variable.
int * a, b, c;
should be :
int *a, *b, *c;
The line :
int * a, b, c;
is interpreted as :
int *a;
int b;
int c;
If you declare variables, do not declare multiple variables on the same line.
What you thought you did was to declare three pointers to int. What you did, was to declare three ints, one of them a pointer:
int* a, b, c;
means
int *a; int b; int c;
Think of the * as belonging to the variable name. Unintuitive, but that's the way the language works.
You want to declare all of the three as pointers:
int* a;
int* b;
int* c;
Change this
int* a, b, c;
to
int *a, *b, *c;
In your declaration you are declaring
a as pointer to int
b as int
c as int
The main problem, as others already noted, are the definitions here:
int* a, b, c;
Basically, only a is an int *; b and c are just ints.
It's just better to have one variable definition per line:
int* a = &a1;
int* b = &a2;
int* c = &a3;
If you use these raw pointers, and if for some reason you want to first define them and then assign their values later, consider at least initializing them to nullptr (or NULL if you are using C++98/03):
// Initialize to NULL/nullptr, to avoid pointers pointing to junk memory
int* a = nullptr;
int* b = nullptr;
int* c = nullptr;
....
// assign proper values to pointers...
Moreover, there are also other notes that can be made for your code:
int main(void)
Since this is C++ - not C - you can omit the (void), and just use () instead:
int main()
When you create the vector:
vector<int *> lol;
lol.clear();
you don't need to call its clear() method after the vector definition: in fact, vector's default constructor (implicitly called by the compiler when you defined the vector in the first line) has already initialized the vector to be an empty vector.
This is just fine:
vector<int *> lol; // Creates an empty vector
Considering these notes, your code can be written something like this:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int *> lol;
int a1 = 1;
int a2 = 2;
int a3 = 3;
int * a = &a1;
int * b = &a2;
int * c = &a3;
lol.push_back(a);
lol.push_back(b);
lol.push_back(c);
cout << *lol[1] << endl;
}
First problem is at declaration of pointers
int* a, b, c;
This will create a as pointer and b & c as int.
Use declaration like
int* a,*b,*c;
And While accessing the elements of vector use .at() method of vector.
cout << *lol.at(0) << endl;

Is my code undefined behavior [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
Is my function has undefined behavior? Becouse there is local variable c, so its in automatic location so it will be destruct after execution of function? (end of scope)
int* calculate(int* a,int* b)
{
int c=(*a)+(*b); //local variable c
return &c;
}
int main()
{
int a=12;
int b=23;
int* ptr=calculate(&a,&b);
std::cout<<*ptr<<endl;
}
Yes, returning a pointer to a temporary local object and dereferencing that is undefined behavior.
Because after exiting the function calculate, that object goes out of scope and automatically will be destroyed, then the provided pointer, points to an invalid address and it's a dangling pointer. After that, you can use dereference and use it (for example: *ptr).
In your case, you can use a normal variable, remove those *:
int calculate(int *a, int *b)
{
int c = (*a)+(*b);
return c;
}
since you have nothing reasonable to pass them by pointer, it's better to remove more *:
int calculate(int a, int b)
{
int c = a + b;
return c;
}
You can pass an int declared in the main, to calculate, like this::
void calculate(int* a,int* b, int* c)
{
*c=(*a)+(*b);
return ;
}
int main()
{
int a=12;
int b=23;
int c=0;
calculate(&a,&b,&c);
std::cout<<c<<endl;
return 0;
}
The much more simpler way is::
int Calculate( int a, int b )
{
return a+b ;
}
int main( void )
{
int a=12, b=23;
std::cout<<Calculate(a,b)<<endl;
return 0;
}