pointers and functions

as of right now this code will compile..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <string>

using namespace std;

void DealDamage(int *EnemyHpPointer, int damage, string EnemyName);

int main()
{
    int EnemyHp;
    int Damage;
    int * EnemyHpPointer;
    EnemyHpPointer = &EnemyHp;
    *EnemyHpPointer = 100;

    cout << "EnemyHp before function call: " << EnemyHp << endl;

    DealDamage(EnemyHpPointer, Damage, "a rat");

    cout << "EnemyHp after function call: " << EnemyHp << endl;

    return 0;
}

void DealDamage(int *EnemyHpPointer, int damage, string EnemyName)
{
    *EnemyHpPointer-=damage;
    cout << "sword does " << damage << " damage " << "to " << EnemyName << endl;
}


the problem is the damage it says it does is in the millions, and the cout EnemyHealth after function call displays -in the millions..

I've tried this..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include <string>

using namespace std;

void DealDamage(int *EnemyHpPointer, int damage, string EnemyName);

int main()
{
    int EnemyHp;
    int Damage;
    int * EnemyHpPointer;
    EnemyHpPointer = &EnemyHp;
    *EnemyHpPointer = 100;

    cout << "EnemyHp before function call: " << EnemyHp << endl;

    DealDamage(*EnemyHpPointer, Damage, "a rat");

    cout << "EnemyHp after function call: " << EnemyHp << endl;

    return 0;
}

void DealDamage(int *EnemyHpPointer, int damage, string EnemyName)
{
    *EnemyHpPointer-=damage;
    cout << "sword does " << damage << " damage " << "to " << EnemyName << endl;
}


but that wont even compile.
So close! You were right the first time. I'll recap anyway, just for anyone else reading this:

DealDamage(*EnemyHpPointer, Damage, "a rat");

What is *EnemyHpPointer? It is "the contents of the memory address that the pointer EnemyHpPointer holds". But you meant to pass the actual pointer! So try

DealDamage(EnemyHpPointer, Damage, "a rat");

Don't forget to give Damage a value, otherwise it will be some garbage value that might be millions...
Last edited on
Hey, that definitely works. That's the beginnings of creating functions that actually matter, lol. It's still a bit confusing...

how come we initialize a pointer as type * name.

assign it to an address without the star, have no idea how to spell astrix, lol.

when we give it a value we have to use the *...

yet when we pass it around we don't...

it makes it a little confusing on when to, and not to use the *
Because the pointer is a complete object in its own right, just like an int or a double. The * has two meanings.


Let's cover the first meaning:
1
2
int b; // Make a new object. The new object is to be an int.
int* a; // Make a new object. The new object is to be an int-pointer 


When we create objects, the "*" is just part of the description of what kind of object we want to make. Once we've made the object, we just use the name of the object.

Here's how we pass the object b that we just made:

someFunction(b);

We don't need to specify that b is an int when we actually use it.

So here's how we pass the pointer we just made:

someOtherFunction(a);

We don't need to specify that a is an int-pointer when we actually use it.

The other use of "*" is as the dereference operator. We use it on a pointer when we don't want the actual pointer; we want what it is pointing at.

1
2
int* c; // Here, "*" is part of the kind of object we want to make
*c; // Here, "*" means dereference the pointer and give us what it points at 


They are two different uses, with two different meanings. If you see int* or double* or string* or any other such <object-type>* it is describing a kind of object. If you see *pointer, it means dereference.

You will see the "describing a kind of object" use in making pointers, and in specifying what kind of objects a function takes (and returns), much like in your function definition

void DealDamage(int *EnemyHpPointer, int damage, string EnemyName);

For this reason, some people would have written this as

void DealDamage(int* EnemyHpPointer, int damage, string EnemyName);

and I tend to stick a p on the front of a name of any object that is a pointer, so that I don't forget that it's a pointer. When you're four thousand lines deep in code, being able to tell by looking if an object is a pointer is a great help. You're doing the same thing by sticking the word Pointer on the end.

void DealDamage(int* pEnemyHp, int damage, string EnemyName);
Last edited on
I won't go into function pointers just yet; just imagine that a function is a lump of code that sits in memory somewhere. What if we made a pointer that contained the memory address of that function? Then, we could pass around that pointer, and we could effectively say "use the function at this memory address". Pretty neat.
I would have to have an increased knowledge of what the uses of knowing such things could lead to. I'm not sure I could think of a good reason at this point to know the location of something in memory, or why I would want to point to a functions memory location.....

I'm sure there's some really advanced things that could be done with such knowledge, but you could say I'm a bit void of that, lol.
Function pointers; imagine that you didn't know at the time of compiling which function would be used. You could have the function pointer, and during running of the program, the decision would be made. For example, we could have two functions with prototypes like this:

1
2
float sin(float input);
float cos(float input);


And a function pointer; that is, a pointer that we specify is pointing to a function that takes a float, and returns a float. The value of that pointer could flip between the two functions repeatedly during running, as needed, and when we use it, we effectively say to the compiler "use the function that this pointer points to at the time of running - you don't need to know or care what the function does, just that it takes a float and returns a float". This is a trivial example, and there are other ways to do this (especially with C++), but it's a powerful low-level mechanism.

I'm not sure I could think of a good reason at this point to know the location of something in memory

Didn't you just do exactly that in your code above when you passed, into your function, a pointer that is the location of EnemyHp in memory? :) That said, the better C++ way is to use a reference, like this:

Be warned - this shows another, completely separate use of the "&" symbol.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>

using namespace std;

void DealDamage(int& EnemyHp, int damage, string EnemyName);

int main()
{
    int EnemyHp = 100;
    int Damage = 12;
 
    cout << "EnemyHp before function call: " << EnemyHp << endl;

    DealDamage(EnemyHp, Damage, "a rat");

    cout << "EnemyHp after function call: " << EnemyHp << endl;

    return 0;
}

void DealDamage(int& EnemyHp, int damage, string EnemyName)
{
    EnemyHp-=damage;
    cout << "sword does " << damage << " damage " << "to " << EnemyName << endl;
}



The difference is essentially here:

1
2
void DealDamage(int& EnemyHp, int damage, string EnemyName);
void DealDamage(int EnemyHp, int damage, string EnemyName);


As you found out in much earlier threads, in the second function, you pass in the values, and whatever happens to those values is lost when the function ends. This is because each value passed in is actually a copy of the original, and that copy is destroyed when the function ends. This is known as pass-by-value.

In the first prototype there, that "&" symbol changes the meaning. It means "the first parameter is a reference to an int". The difference is that a copy is not made; the function will work directly with the original value - the exact same bit of memory, not a copy of the value made just for the function. Clearly, then, if it's working with the original object, any changes happen to that original object, and those changes are permanent - when the function ends, the original has been changed.
Last edited on
Topic archived. No new replies allowed.