Can you explain me which is the mechanism behind the next code samples (I think I know but I need second opinion):
1)--------------------------
using namespace std;
int * f(int x) {
return &x;
}
int * g(int x, int y) {
return &y;
}
int * h(int x, int y, int z) {
return &z;
}
int main() {
cout << *f(42) << endl;
int * y1 = g(43, 44);
int * y2 = g(45, 46);
cout << *y1 << ", " << *y2 << endl;
int * z1 = h(47, 48, 49);
int * z2 = h(50, 51, 52);
cout << *z1 << ", " << *z2 << endl;
return 0;
}
2)--------------------------
int *a, *b;
void f(int x) {
int i[3];
i[0] = x;
i[1] = x + 1;
i[2] = x + 2;
a = i;
}
void g(int x) {
int i[3];
i[0] = x;
i[1] = x + 1;
i[2] = x + 2;
b = i;
}
int main() {
f(1);
printf("a = {%d,%d,%d}\n", a[0], a[1], a[2]);
g(2);
printf("a = {%d,%d,%d}\n", a[0], a[1], a[2]);
}
3)--------------------------
int main() {
char * hello = "hello, world!" + 3;
char * charstring = 'h' + "ello, world!";
printf("hello=%s, charstring=%s.\n", hello, charstring);
return 0;
}
Thank you.
I would expect those programs to crash or do other weird things when you run them.
Example 1: The functions f, g and h are returning the memory addresses of their arguments. Note that those arguments are stored on the stack, and when the functions return, the stack is unwound and the addresses will not be valid anymore. You could get lucky and the value will still be there, but you could just as well have the program crash or return some random value that's not the value that you passed to the function.
Example 2: The functions f and g set the global variables a and b to the addresses of local variables declared in the functions. Just like in the first example, those local variables will be gone when the functions return, leaving a and b pointing to something invalid.
Example 3: This is doing weird pointer arithmetic. hello will probably point to the address of the text plus 3, so you'd probably get "lo, world!" printed for this (but it could also be different, depending on how pointer arithmetic works on your particular platform). The case with charstring is similar, only here you add 'h' (ASCII value 104 - so you're adding 104 to the pointer). This will most likely crash the program.
I think it's a little easier for a beginner to understand these concepts if you explain step by step what is happening in the background.
1.
cout << *f(42) << endl; // Call f with the value 42
int * f(int x) { // Push an integer, x, on the stack (x = 42)
return &x; // Return a pointer to var x
} // Pop x off the stack
// Pointer now points to a memory address that is unallocated,
// which will crash the program when it tries to use that memory,
// which it does with cout
2.
f(1); // Call f with the value 1
void f(int x) { // Push an integer, x, on the stack (x = 1)
int i[3]; // Declare an int* with space for 3 vals (local! stack!)
i[0] = x; // Define values of the array
a = i; // Set a equal to i, beginning of array
} // i is now out of scope, and since it was declared as locally,
// rather than with malloc (or new in c++), it is on the stack
// and has now been popped off, so a points to a memory address
// that the OS *should* have marked as inaccessible
3.
char * hello = "hello, world!" + 3; // hello is a char*, a pointer that
// points to the beginning of an array
// of characters. Adding 3 will increment
// the pointer three characters after the
// first character.
char * charstring = 'h' + "ello, world!"; // charstring is a char*, a pointer that
// points to the beginning of an array
// of characters. This time, it would point
// to "ello, world!". However, the addition
// of 'h' will shift the character position
// by 104 characters because that is the
// value of ascii 'h'.
Related
I saw some codes on the web and trying to figure out how this works. I tried to leave comments on each lines but I cannot understand why y[0] changes to 5555. I'm guessing y[0] might change to numbers[0], but why?
x value is still 1. Well.. is this because y[0] = 1; has no int data type?
#include
using namespace std;
void m(int, int []);
/*this code explains a variable m that m consists of two parts, int and int array*/
int main()
{
int x = 1; /* x value is declared to 1*/
int y[10]; /*Array y[10] is declared but value is not given*/
y[0] = 1; /*Array y's first value is declared to 1 but data type is not given*/
m(x, y); /*This invokes m with x and y*/
cout << "x is " << x << endl;
cout << "y[0] is " << y[0] << endl;
return 0;
}
void m(int number, int numbers[]) /*variable names in m are given, number and numbers.*/
{
number = 1001; /*number has int 1001 value*/
numbers[0] = 5555; /*This overrides y to numbers[], so y[0] =1 changes to numbers[0] = 5555.*/
}
/*This program displays
* x is 1
* y[0] is 5005
* y[0] value has changed but x has not.
* */
I'm guessing y[0] might change to numbers[0], but why? x value is still 1.
Don't guess please. Your code works as commonly expected.
number = 1001; doesn't influence x in any way.
number is a local copy (as passed by value).
numbers decays to a pointer to the 1st element of the original array, thus it is changed outside the functions scope.
Well.. is this because y[0] = 1; has no int data type?
No, as explained above. y[0] actually is of type int.
int numbers[] is almost equivalent to int* numbers in this situation. You are not passing the vector as an immutable object but as a reference. So both numbers ( the local variable from the function ) and y ( the local variable from main ) will be pointing to the same memory address.
Calculate nth power of P (both p and n are positive integer) using a recursive function myPowerFunction(int p, int n, int ¤tCallNumber). currentCallNumber is a reference parameter and stores the number of function calls made so far. myPowerFunction returns the nth power of p.
int myPowerFunction(int p, int n, int &z)
{
z++;
if(n==1)return p;
else if(n==0)return 1;
else if(n%2==0)return myPowerFunction(p,n/2,z)*myPowerFunction(p,n/2,z);
else return myPowerFunction(p,n/2,z)*myPowerFunction(p,n/2,z)*p;
}
int main()
{
cout << myPowerFunction(3,4,1);
}
You need a variable to pass as the third argument in main_program. You can't pass a constant as a non-const reference.
int count = 0;
std::cout << myPowerFunction(3, 4, count) << 'n';
std::cout << count << '\n';
Third parameter expects a lvalue, so you cannot pass numeric constant there, so possible solution can be:
int z = 1;
cout<< myPowerFunction(3,4,z);
or better to create a function that calls recursive one:
int myPowerFunction(int p, int n)
{
int z = 1;
return myPowerFunction(p,n,z);
}
In myPowerFunction(3,4,1) the literal 1 cannot be passed to a non const reference as it is a prvalue [basic.lval]. You need to store the value into a variable and then use that variable when calling the function.
int z = 0;
std::cout << myPowerFunction(3, 4, z);
You don't have to give a reference as parameter as many here state.
But yes, your input for z cannot be modified as it comes from read-only memory. Treat the input for z as const, copy z internally and give the copy as reference. Then your desired usage works:
int myPowerFunction(int p, int n, const int &z) // z is now const !
{
int _z = z + 1; // copy !
if (n == 1) return p;
else if (n == 0) return 1;
else if (n % 2 == 0) return myPowerFunction(p, n /2 , _z) * myPowerFunction(p, n / 2, _z);
else return myPowerFunction(p, n / 2, _z) * myPowerFunction(p, n / 2, _z) * p;
}
int main()
{
std::cout << myPowerFunction(3, 4, 1);
}
I was writing a program for finding roots for a class, and had finished and got it working perfectly. As I go to turn it in, I see the document requires the .cpp to compile using Visual Studio 2012 - so I try that out. I normally use Dev C++ - and I've come to find it allows me to compile "funky things" such as dynamically declaring arrays without using malloc or new operators.
So, after finding the error associated with how I wrongly defined my arrays - I tried to fix the problem using malloc, calloc, and new/delete and well - it kept giving me memory allocation errors. The whole 46981239487532-byte error.
Now, I tried to "return" the program to the way it used to be and now I can't even get that to work. I'm not even entirely sure how I set up the arrays to work in Dev C++ in the first place. Here the code:
#include <iostream>
#include <stdlib.h>
#include <math.h>
using namespace std;
float newton(float a, float b, float poly[],float n, float *fx, float *derfx);
float horner(float poly[], int n, float x, float *derx);
float bisection(float a, float b, float poly[], float n, float *fx);
int main(int argc, char *argv[])
{
float a, b, derr1 = 0, dummyvar = 0, fr1 = 0, fr0;
float constants[argc-3];
//float* constants = NULL;
//constants = new float[argc-3];
//constants = (float*)calloc(argc-3,sizeof(float));
//In order to get a and b from being a char to floating point, the following lines are used.
//The indexes are set relative to the size of argv array in order to allow for dynamically sized inputs. atof is a char to float converter.
a = atof(argv[argc-2]);
b = atof(argv[argc-1]);
//In order to get a easy to work with array for horners method,
//all of the values excluding the last two are put into a new floating point array
for (int i = 0; i <= argc - 3; i++){
constants[i] = atof(argv[i+1]);
}
bisection(a, b, constants, argc - 3, &fr0);
newton(a, b, constants, argc - 3, &fr1, &derr1);
cout << "f(a) = " << horner(constants,argc-3,a,&dummyvar);
cout << ", f(b) = " << horner(constants,argc-3,b,&dummyvar);
cout << ", f(Bisection Root) = " << fr0;
cout << ", f(Newton Root) = "<<fr1<<", f'(Newton Root) = "<<derr1<<endl;
return 0;
}
// Poly[] is the polynomial constants, n is the number of degrees of the polynomial (the size of poly[]), x is the value of the function we want the solution for.
float horner(float poly[], int n, float x, float *derx)
{
float fx[2] = {0, 0};
fx[0] = poly[0]; // Initialize fx to the largest degree constant.
float derconstant[n];
//float* derconstant = NULL;
//derconstant = new float[n];
//derconstant = (float*)calloc(n,sizeof(float));
derconstant[0] = poly[0];
// Each term is multiplied by the last by X, then you add the next poly constant. The end result is the function at X.
for (int i = 1; i < n; i++){
fx[0] = fx[0]*x + poly[i];
// Each itteration has the constant saved to form the derivative function, which is evaluated in the next for loop.
derconstant[i]=fx[0];
}
// The same method is used to calculate the derivative at X, only using n-1 instead of n.
fx[1] = derconstant[0]; // Initialize fx[1] to the largest derivative degree constant.
for (int i = 1; i < n - 1; i++){
fx[1] = fx[1]*x + derconstant[i];
}
*derx = fx[1];
return fx[0];
}
float bisection(float a, float b, float poly[], float n, float *fx)
{
float r0 =0, count0 = 0;
float c = (a + b)/2; // c is the midpoint from a to b
float fc, fa, fb;
int rootfound = 0;
float *derx;
derx = 0; // Needs to be defined so that my method for horner's method will work for bisection.
fa = horner(poly, n, a, derx); // The following three lines use horner's method to get fa,fb, and fc.
fb = horner(poly, n, b, derx);
fc = horner(poly, n, c, derx);
while ((count0 <= 100000) || (rootfound == 0)) { // The algorithm has a limit of 1000 itterations to solve the root.
if (count0 <= 100000) {
count0++;
if ((c == r0) && (fabs(fc) <= 0.0001)) {
rootfound=1;
cout << "Bisection Root: " << r0 << endl;
cout << "Iterations: " << count0+1 << endl;
*fx = fc;
break;
}
else
{
if (((fc > 0) && (fb > 0)) || ((fc < 0) && (fb < 0))) { // Checks if fb and fc are the same sign.
b = c; // If fc and fb have the same sign, thenb "moves" to c.
r0 = c; // Sets the current root approximation to the last c value.
c = (a + b)/2; // c is recalculated.
}
else
{
a=c; // Shift a to c for next itteration.
r0=c; // Sets the current root approximation to the last c value.
c=(a+b)/2; // Calculate next c for next itteration.
}
fa = horner(poly, n, a, derx); // The following three send the new a,b,and c values to horner's method for recalculation.
fb = horner(poly, n, b, derx);
fc = horner(poly, n, c, derx);
}
}
else
{
cout << "Bisection Method could not find root within 100000 itterations" << endl;
break;
}
}
return 0;
}
float newton(float a, float b, float poly[],float n, float *fx, float *derfx){
float x0, x1;
int rootfound1 = 1, count1 = 0;
x0 = (a + b)/2;
x1 = x0;
float fx0, derfx0;
fx0 = horner(poly, n, x0, &derfx0);
while ((count1 <= 100000) || (rootfound1 == 0)) {
count1++;
if (count1 <= 100000) {
if ((fabs(fx0) <= 0.0001)) {
rootfound1 = 1;
cout << "Newtons Root: " << x1 << endl;
cout << "Iterations: " << count1 << endl;
break;
}
else
{
x1 = x0 - (fx0/derfx0);
x0 = x1;
fx0 = horner(poly, n, x0, &derfx0);
*derfx = derfx0;
*fx = fx0;
}
}
else
{
cout << "Newtons Method could not find a root within 100000 itterations" << endl;
break;
}
}
return 0;
}
So I've spent the past several hours trying to sort this out, and ultimately, I've given in to asking.Everywhere I look has just said to define as
float* constants = NULL;
constants = new float[size];
but this keeps crashing my programs - presumably from allocating too much memory somehow. I've commented out the things I've tried in various ways and combonations. If you want a more tl;dr to the "trouble spots", they are at the very beginning of the main and horner functions.
Here is one issue, in main you allocate space for argc-3 floats (in various ways) for constants but your code in the loop writes past the end of the array.
Change:
for( int i = 0; i<=argc-3; i++){
to
for( int i = 0; i<argc-3; i++){
That alone could be enough to cause your allocation errors.
Edit: Also note if you allocate space for something using new, you need to delete it with delete, otherwise you will continue to use up memory and possibly run out (especially if you do it in a loop of 100,000).
Edit 2: As Galik mentions below, because you are using derconstant = new float[n] to allocate the memory, you need to use delete [] derconstant to free the memory. This is important when you start allocating space for class objects as the delete [] form will call the destructor of each element in the array.
I've having trouble understanding the wording of this question and what it means by returning the second value through a pointer parameter?
The problem is:
Write a function that takes input arguments and provides two seperate results to the caller, one that is the result of multiplying the two argumentsm the other the result of adding them. Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter.
This is what I've done so far.
int do_math(int *x, int *y)
{
int i =*x + *y;
int u = *x * *y;
int *p_u = &u;
return i;
}
void caller()
{
int x = 10;
int y = 5;
std::cout << do_math(&x, &y);
//std::cout << *u;
}
I think all they're wanting you to do is to demonstrate your understanding of the difference between passing arguments by value and passing them by reference.
Here is a sample code that shows that although my function is only returning one value "i = X+Y", It is also changing the value of Y to (Y * X).
Of course if you do need Y's value to stay unchanged, you could use a third variable that is equal to Y's value and pass its reference as an extra argument to your function.
You could run the code bellow to see what's happening to X and Y before and after calling the function.
Hope this helps.
#include <iostream>
using namespace std;
int do_math(int value1, int *pointer_to_value2)
{
int i = value1 * *pointer_to_value2;
*pointer_to_value2 = *pointer_to_value2 + value1; // y changes here
return i;
}
int main( int argc, char ** argv ) {
int x = 10;
int y = 5;
cout << "X before function call " << x << endl;
cout << "Y before function call " << y << endl;
int product = do_math(x, &y);
cout << "X after function call " << x << endl;
cout << "Y after function call " << y << endl;
cout << "What the function returns " << product << endl;
return 0;
}
In the assignment there is written
Write a function that takes input arguments ...
So there is no any need to declare these input parameters as pointers.
The function could look like
int do_math( int x, int y, int &sum )
{
sum = x + y;
return x * y;
}
or
int do_math( int x, int y, int *sum )
{
*sum = x + y;
return x * y;
}
In these function definitions the sum and the product can be exchanged as the parameter and return value
As for me the I would write the function either as
void do_math( int x, int y, long long &sum, long long &product )
{
sum = x + y;
product = x * y;
}
or
#include <utility>
//...
std::pair<long long, long long> do_math( int x, int y )
{
return std::pair<long long, long long>( x + y, x * y );
}
void caller()
{
int x = 10;
int y = 5;
std::pair<long long, long long> result = do_math( x, y );
std::cout << "Sum is equal to " << result.first
<< " and product is equal to " << result.second
<< std::endl;
}
Edit: I would like to explain why this statement
std::cout << "sum is " << do_math(x, y, result) << " and result is " << result;
is wrong.
The order of evaluation of subexpressions and function argument is unspecified. So in the statement above some compilers can output value of result before evaluation function call do_math(x, y, result)
So the behaviour of the program will be unpredictable because you can get different results depending on using the compiler.
Edit: As for your code from a comment then it should look like
#include <iostream>
int do_math( int x, int y, int *p_u )
{
int i = x + y;
*p_u = x * y;
return i;
}
int main()
{
int x = 10;
int y = 5;
int u;
int i = do_math( x, y, &u );
std::cout << i << std::endl;
std::cout << u << std::endl;
}
Also take into account that in general case it is better to define variables i and u as having type long long because for example the product of two big integers can not fit in an object of type int.
The wording is kind of contrived but I believe the task asks you to
return the multiplication as the return value of the function, and
since you can't return two types at once (except if you wrap them up somehow), you should use a third parameter as a storage area for the sum:
#include <iostream>
/* Multiplication in here */ int do_math(int x, int y, int& result/* Addition in here */)
{
result = x + y;
return x*y;
}
int main() {
int x = 10;
int y = 5;
int addition = 0;
int multiplication = do_math(x, y, addition);
std::cout << "multiplication is " << multiplication << " and sum is " << addition;
}
Example
It's not specifically asking you to use two parameters for the function.
A typical solution to the intent of the exercise text…
” Write a function that takes input arguments and provides two seperate results to the caller, one that is the result of multiplying the two argumentsm the other the result of adding them. Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter
… is
auto product_and_sum( double& sum, double const a, double const b )
-> double
{
sum = a + b;
return a*b;
}
#include <iostream>
using namespace std;
auto main() -> int
{
double product;
double sum;
product = product_and_sum( sum, 2, 3 );
cout << product << ", " << sum << endl;
}
This code is unnatural in that one result is returned while the other is an out-argument.
It's done that way because the exercise text indicates that one should do it that way.
A more natural way to do the same is to return both, as e.g. a std::pair:
#include <utility> // std::pair, std::make_pair
using namespace std;
auto product_and_sum( double const a, double const b )
-> pair<double, double>
{
return make_pair( a*b, a+b );
}
#include <iostream>
#include <tuple> // std::tie
auto main() -> int
{
double product;
double sum;
tie( product, sum ) = product_and_sum( 2, 3 );
cout << product << ", " << sum << endl;
}
As the second program illustrates, the last sentence of the exercise text,
” Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter
… is just not true. I suspect the author had meant the word “directly” to clarify that this excluded the case of a non-basic type. But even so the conclusion is incorrect.
What you need to do is provide another parameter to the function - the pointer or the reference to the variable where you want to store your other result:
int do_math(int *x, int *y, int &res) //or int *res
{
...
res = *x * *y;
...
}
Then make a result variable in main and pass it to the function
This is a code snippet I created for learning purposes in C++, I am currently trying to teach myself. My question is:
Why does *ptr = 30 change the output values of the two last cout statements in my main? (the output is 30, 30, 30). Consequently, why does int y = 30; and ptr = &y; not change the output in my main, and stay local to the function? (if I comment out *ptr = 30, and not the former two statements, the output is 30, 5, 5)
If I change the function input to void printPointer(int *&fptr) -- and comment out only *ptr = 30 -- then *ptr in my main will be modified, but not x. I understand this, as the pass by reference is modifying the pointer, but not how my first statement modifies *ptr and x in my main.
#include <iostream>
using namespace std;
void printPointer(int *fptr);
int main()
{
int x = 5;
int *ptr = &x;
printPointer(ptr);
cout << *ptr << endl;
cout << x << endl;
return 0;
}
void printPointer(int *fptr)
{
// int y = 30; // this does not change the output of the last two couts in main, output = 30, 5, 5
// fptr = &y;
*fptr = 30; // uncommenting this and commenting out the former two statements: output = 30, 30, 30
cout << *fptr << endl;
}
*ptr = 30 changes the value of what is being pointed at. In your case, you have set ptr to point at x (when you did ptr = &x and then passed that in as the argument to printPointer()). So the value of x is changed.
When you instead do int y = 30; fptr = &y;, all you're doing is changing fptr to point at a different variable. That's it. You're not changing the value of what is being pointed to (i.e. the value of x). And you're not affecting ptr, because fptr is a separate, local, variable. So ptr still points at x, and x is still 5.
When you modify your function to take the pointer by reference, then changing fptr to point at y also changes ptr, because they are the same variable.
*fptr = 30 would dereference the address stored in fptr and write 30 at the position in memory. this address in memory you gave to the function with printPointer(ptr). ptr in this case was the address of x, which you assigned to ptr with ptr = &x.
int y= y declares a variable local to the function.
fptr = &y assigns the address of y to fptr (and overwrites the value from ptr). so the last line in this case would change the local variable y instead of x.
If I understand correctly, you're asking about two pieces of code. The first one is what you posted:
#include <iostream>
using std::cout;
void f(int* fptr) {
*fptr = 30; // 11
cout << "*fptr = " << *fptr << '\n'; // 12
}
int main() {
int x = 5; // 1
int* ptr = &x; // 2
f(ptr); // 21
cout << "*ptr = " << *ptr << '\n'; // 22
cout << "x = " << x << '\n'; // 23
}
In this case, the pointer always points to x, and in the function, you still change the value of x, as that is what fptr is pointing to. If it helps, here's a demonstration of the value of the variables at the end of every line: NE means a variable does not currently exist.
1. x = 5, ptr = NE, fptr = NE
2. x = 5, ptr = &x, fptr = NE
11. x = 30, ptr = &x, fptr = &x
12. x = 30, ptr = &x, fptr = &x
21. x = 30, ptr = &x, fptr = NE
After that, the values do not change, and all three statements will print 30.
The second one is:
#include <iostream>
using std::cout;
void f(int*& fptr) {
int y = 30; // 11
fptr = &y; // 12
cout << "*fptr = " << *fptr << '\n'; // 13
}
int main() {
int x = 5; // 1
int* ptr = &x; // 2
f(ptr); // 21
cout << "*ptr = " << *ptr << '\n'; // 22
cout << "x = " << x << '\n'; // 23
}
In the first case, the pointer is passed by reference, and it points to y. In fact, in this case, line 21 involves undefined behaviour, as y no longer exists. Again, line-by-line analysis:
1. x = 5, y = NE, ptr = NE, fptr == NE
2. x = 5, y = NE, ptr = &x, fptr == NE
11. x = 5, y = 30, ptr = &x, fptr == ptr
12. x = 5, y = 30, ptr = &y, fptr == ptr
13. x = 5, y = 30, ptr = &y, fptr == ptr
21. x = 5, y = NE, ptr = &y, fptr == NE
The values again do not change after this: however, on line 22, you try to take the address of ptr. As you can see, *ptr = y = NE, and thus the behaviour is undefined. The output can be anything.
(Another note is that you should avoid using namespace std; as it can cause name clashes; use using std::cout; and similar, as in the code above.)