I just started on STRUCTURES, played with them a little and got burnt!
This is the 1st exhibition:
#include <iostream>
using namespace std;
struct structure1{
int h;
int m;
int s;
} structVar;
int func(structure1 x);
int main(){
structure1 x;
structVar.h=4;
structVar.m=6;
structVar.s=7;
func(structVar);
cout<<x.h<<x.m<<x.s<<endl;
}
int func(structure1 x){
--x.h;
--x.m;
--x.s;
};
Its output is:
1072276636-21953788778
But I expect:
356
So I tried this way, exhibition 2:
#include <iostream>
using namespace std;
struct structure1{
int h;
int m;
int s;
} structVar;
struct returnstruct{
int val1;
int val2;
int val3;
}returnvalue;
int func(structure1 x);
int main(){
structVar.h=4;
structVar.m=6;
structVar.s=7;
func(structVar);
cout<<returnvalue.val1<<returnvalue.val2<<returnvalue.val3<<endl;
}
int func(structure1 x){
returnvalue.val1=--x.h;
returnvalue.val2=--x.m;
returnvalue.val3=--x.s;
};
And got my required output:
356
Problem is I cant explain why
This confusion is mostly due to variable scoping.
Key points:
function parameter names, such as x, are local to the function. If a name conflict exists with a globally scoped variable, the local function parameter will take precedence.
structs are passed by value, which means a copy is made and passed to the function as the parameter.
Case 1, you have the structure definition for a struct called structure1. In this global scope you also have an instance of it, called structVar. Then inside the scope of the main function, you have defined a local variable of type structure1 called x. The following lines
structVar.h=4;
structVar.m=6;
structVar.s=7;
are modifying the global scoped variable, structvar. Then you call
func(structVar);
This line modifies a copy of the global variable, structVar by passing it in as a function parameter to func. func uses the name, x for its reference to a structure1, but remember, since structs are passed by value, this name is referring to a copy of whichever struct you pass to it between the parens - func(structVar). This parameter name, x, has no relationship to the other x defined in main. It is specific or scoped to the body of the function, func.
You can explore this a bit, by changing the name of the function parameter to y, and first notice that it will not compile, complaining about x being undefined. This means that within the body of that function, it doesn't know about the x you've defined in main because that x is local aka scoped only to main. Contrast this with structVar, which is defined outside of any function's parameter list or body. structVar can be referred to within either of the functions because its scope is global.
cout<<x.h<<x.m<<x.s<<endl;
Using this understanding of scope, this line then can be seen to operating on the x defined in main which has not had its members (h,m,s) initialized or assigned any values, thus the 'weird' output.
Now, let's look at the second block of code you posted.
Here, you've added another global scope struct, called returnvalue. Now, you have two global scope variables, structVar and returnvalue. Because of that scope, structVar is visible inside of main, where you are modifying its member values (h,m,s).
Next, you are passing that global variable to func as its parameter, x. Remember, this is making a copy of structVar, which func calls x. So, x has the values of structVar's h, m, and s.
Inside of func, because of that global scope, it can see returnValue. Using the copy of structVar, again now called x, you are setting the values of returnvalue to the (pre)decremented (--) values of the parameter x. Since x is a copy of structVar and structVar had its members set to the numbers h=4, m=6, s=7, returnvalue then receives h=3, m=5, s=6. func then returns back to main.
Now, back in main, since returnvalue is global scope, main can see it and print out its values using cout, thus the output of 356
The value of structure1 x is passed by value. That means that the func function gets a copy of the argument that the caller never sees. So func can have no effect in this context unless it returns something.
You can either return the modified structure of pass x by reference, e.g., structure1& x. In the latter case x refers to the object that the function was called with.
#include <iostream>
using namespace std;
struct structure1{
int h;
int m;
int s;
} structVar;
int func(structure1 x);
int main(){
structure1 x;
structVar.h=4;
structVar.m=6;
structVar.s=7;
func(structVar);
I changed the line below
cout<<structVar.h<<structVar.m<<structVar.s<<endl;
}
I changed the function below too
int func(structure1 x){
--structVar.h;
--structVar.m;
--structVar.s;
};
Output is 356 as expected
Related
Why the output is 30 here? And how fun()=30 is valid? What is meant by assigning function a value? And why removing static keyword throws segmentation fault?
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
Let's walk through your program step by step:
inside main() fun() is called.
fun() has a static variable x (static means, that x is stored in a special part of memory and not on the stack, so its value is preserved between function calls) (It's like having a global variable that is only visible from inside fun())
fun() returns a reference to x (references are almost like pointers)
You write to the returned reference of x, so x actually gets changed! (You don't write to the function)
now x is 30 and fun() returns 30 on the next call.
I hope this answers your first three questions.
Why you get a segmentation fault without the static keyword:
In this case x does exist on the stack. So whenever you call fun() some memory gets allocated on the stack to hold x. When fun() returns, this memory will be deallocated.
Now, the reference returned by fun(), will reference a piece memory, that is not allocated by your program anymore. In other words, the returned reference will reference a memory address, that does "not belong to your program", thus you are not allowed to write to it. And so you get a segmentation fault.
Can we assign values to function:
To answer the actual title of your question: Yes, we can, using function pointers:
int foo(int x) {
return x + 1;
}
int bar(int x) {
return x * 2;
}
void main() {
int(*f)(int) = foo;
// int the function pointed to returns an int
// (*f) f is the name of the function pointer
// (int) the function pointed to takes on int as paramter
// = foo; f now points to the function foo()
(*f)(3); // the same as foo(3), returns 4
f = bar; // now f points to bar()
(*f)(3); // the same as bar(3), returns 6
}
fun() returns a reference to static variable x, to which you assign the value 30. You don't assign anything to the function itself. In fact, it is not possible to assign anything to a function in C++.
In the below code the variable a is passed to a constructor by reference, received by the parameter x. Then x is passed as a reference to an attribute. The attribute is then initialized with value 3. The program outputs the value 3 when running.
MY QUESTION
Shouldn't the program crash or show 2 because after the constructor is called
x should go out of scope and be released and its address should be freed right. and trying to write to it should give a memory access violation. However in this case the x is still in program control holding the address of 'a'
Is this valid c++ behavior or am i missing something?
#include <iostream>
#include <conio.h>
using namespace std;
class myclass {
public:
int& attribute;
myclass(int& x):attribute(x) {
}
void func() {
attribute = 3;
}
};
int main() {
int a = 2;
myclass obj(a);
obj.func();
std::cout << a;
_getch();
}
No this program is fine. attribute is a reference to a. The fact that x has gone out of scope is neither here nor there.
If you changed your code to
myclass(int x):attribute(x)
then that would be a problem.
The behavior of the program line by line
variable "a" is initialized with value 2
int a = 2;
Initialize obj with the variable a
myclass obj(a);
First x becomes the reference to a, then attribute becomes the reference to x. Consequently, attribute becomes the reference to a, which has the value 2 at the moment.
myclass(int& x):attribute(x) {}
Call func() of obj
obj.func();
attribute is the reference to a.
Both "attribute" and "a" are changed to 3. Consider them as the same,
single variable, just with difference alias.
That means, at this moment, attribute and a refers to the same variable,
and can be used interchangeably.
void func() {
attribute = 3;
}
My struct:
struct Point {
int x;
int y;
Point(int nX, int nY) { x = nX; y = nY; }
Point() {};
};
Function:
void functionName(Point target);
And I want declare variable in function call: (pseudocode)
functionName(Point variable(5,0));
I'm writing in C or C++.
If you meant to construct a temporary Point and pass it to the function, you could (for C++):
functionName(Point(5,0));
Or for C++11:
functionName(Point{5,0});
[For C, ignoring the c'tor and d'tor]
struct Point {
int x;
int y;
};
Use a compound literal like this:
functionName((struct Point){5, 0});
Please not that the compound literal defined by this lives on the stack of the current context until the context is left.
To have it be deallocated immediately the function return, wrap the function call in its own context by doing:
{
functionName((struct Point){5, 0});
}
In case you want to use that variable, after the function finishes (I think you might as well do, since you want to give your argument a name), you would probably want to pass ref/pointer, for example :
void functionName(Point& target);
Point variable(5,0);
functionName(variable);
In case you dont really need the variable, you can simply pass an rvalue, by calling the constructor as argument :
functionName(Point(5,0));
notice that the 'target' will be destroyed when the function returns.
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
when the above program is run,the output is 30.The integer variable x was returned,as a reference to the main() function and it is assigned the value of 30.But isn't the scope of x limited to the fun() function?;If so,why are we able to change the value of it in main function??
Scope is limited means any attempt to access x directly outside the scope is forbidden.
Within a scope, unqualified name lookup can be used to associate the
name with its declaration.
But you can always return a pointer or reference to this variable if variable is alive and you change it through that reference or pointer which points to the same variable. The name of this reference may be anonymous (temporary) or may be bound to some named reference.
About lifetime, it starts when the function containing static variable is called first time and ends when the program end.
Indeed the scope of x is limited to fun().
But because that function returns a reference to x, the caller (i.e. main) is able to modify x through that reference. That's what's happening here: x is set to 10 the first time the function is entered, but is changed to 30 by the assignment fun() = 30.
typedef double real8;
typedef real8 Real_t;
Real_t& x(int y);
What is Real_t& ?? I've only seen a datatype followed by "&" to indicate pass by reference.
But this is in declaration line. What does this mean ?
This means that the function returns a reference to a Real_t which is actually a double. The Real_t is a real8 which is a double if you resolve all the typedefs.
You should be careful here. If the result being passed by reference isn't retrieved from a scope that exists pasts the end of the function, then you'll have a dangling reference.
For example:
int& foo() {
int x = 8;
return x;
}
int main() {
int y = foo();
}
The variable, y, in main ends up referring to a variable which has been destroyed as it went out of scope when foo() returned, so using it is undefined behavior. If x had been retrieved from a singleton or something that lives outside the scope of the function foo(), then it would still exist though and this would be fine.
People sometimes return references to initialize static globals in a deterministic way between compilation units, so you might see this used with statics like:
MyClass& MyStaticVar() {
static MyClass instance;
return instance;
}
Which is also okay, because the static lives for the duration of the program after initialized.
It means x is a function that returns a reference to a Real_t.
An example of returning by reference is for data access in classes. For example, std::vector::at() returns a reference to an element of the vector.
For a free function to safely return a reference, there must be something non-obvious going on inside the function to ensure that a dangling reference isn't returned.