Learning C++ pointers help

0efe53f7a0e80918b40990d256cb4fe1
0
KR3M3R 101 Jan 06, 2007 at 07:39

Hi, I appreciate any help you guys can give me, I’m trying to learn C++ on my own, and was hoping you could tell me if I’m on the right track with respect to pointers.

First question:

int *pi2 = new int(1024);

this creates a pointer to an integer value of 1024 (as i understand it).
if I wanted to create a variable to use this value could I do this:

int num = *pi2; //?

or would I do this:

int num = **pi2;

or this:

int num = &pi2;

Second question:
int *pi3 = new int[1024];
As i understand it this creates an integer array of 1024 values pointed to by pi3. Is it possible to create a variable to access this array directly (and is that a desirable goal)?

As I’ve said I’m just learning this stuff and really appreciate your help and time in answering this question. Thanks again.
-Robb

16 Replies

Please log in or register to post a reply.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 168 Jan 06, 2007 at 08:46

If pi2 is a pointer to an integer, than *pi2 is the integer value pointed to. This is called dereferencing the pointer. Conversely, if num is an integer, then &num is a pointer to num. So, num == *(&num), and pi2 == &(*pi2).

To declare an array without using new, you can write:
int nums[1024];
Note that arrays and pointers are syntactically identical in C++. This means you can use the name of an array as a pointer. Here, nums is an array, but it is also a pointer to the first element of the array. So, *nums == nums[0]. Conversely, any pointer can be accessed using array syntax, so *pi2 == pi2[0], and also pi2 == &pi2[0]. Moreover, array subscripting is equivalent to adding to a pointer. Therefore, num + 8 == &num[8], and *(num + 8) == num[8].

The difference between creating something using new and declaring it directly is all memory allocated with new has to be freed with delete, and things directly declared will be automatically de-allocated when they go out of scope. Generally, you will want to use static declarations unless you need to allocate dynamically. Some cases where you would need to use new:
(a) you want the allocated memory to hang around longer than normal, for instance if you’re returning a pointer to it (since it would normally be destroyed when the function returns);
(;) you don’t know until runtime how much memory you need. You can only declare static arrays with constant sizes, while you can use new to get arrays with variable sizes.

36b416ed76cbaff49c8f6b7511458883
0
poita 101 Jan 07, 2007 at 03:50

Pointers are just variables that hold memory addresses instead of the usual numerical values. The dereferencing operator (*) returns the value stored in the memory location that the pointer holds. The opposite of the dereferencing operator is the referencing operator (&), which returns the address of the operand.

int *pi2 = new int(1024);

As you know, this creates a pointer to an integer value of 1024. More specifically it creates a pointer to a memory address that has the integer value of 1024. The ‘new’ keyword allocates some memory for the integer and returns the memory address, which is now stored in pi2.

int num = *pi2;

So what does this do? The dereferencing operator (*) goes to the address pointed to by pi2 and gets the value stored there. As you know, pi2 points to a memory address that has 1024 stored there so this will make num == 1024.

int num = **pi2;

Now what you are doing here is dereferencing twice. We already know that *pi2 == 1024 so **pi2 == *(1024) == the value stored at memory address 1024. We have no idea what is stored at memory addess 1024 so it would most likely be some random integer, definitely not what you want to do.

int num = &pi2;

The referencing operator (&) returns the address of pi2. So you would most likely end up setting num to something like 2382346353 i.e. some random number that represents the memory address of pi2.

As Reedbeta already pointed out (pardon the pun), arrays and pointers are actually the same thing. What he means by that is that when you do something like this:

int nums[1024];

You are actually creating a pointer to the first element in the array. IMO it’s not terribly obvious and can be quite confusing since there’s nothing really there saying that you’re creating a pointer but that is what you are doing and it’s something you need to remember, especially when it comes to passing arrays as arguments to functions.

The most important thing to remember is that &(*p) == *(&p) == p. This is the pointer identity. Got a pointer to a pointer to a pointer? Just reference it 3 times and you’re back at the value.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Jan 07, 2007 at 13:55

@poita

int num = **pi2; Now what you are doing here is dereferencing twice. We already know that *pi2 == 1024 so **pi2 == *(1024) == the value stored at memory address 1024. We have no idea what is stored at memory addess 1024 so it would most likely be some random integer, definitely not what you want to do.

Of course, you can’t just dereference an int, you have to reinterpret_cast it to a pointer first ;)

int num = &pi2; The referencing operator (&) returns the address of pi2. So you would most likely end up setting num to something like 2382346353 i.e. some random number that represents the memory address of pi2.

As above but just the other way around. &pi2 yields a pointer (that points to a pointer, namely pi2), and num is an int. You can’t assign a pointer to an int without doing a reinterpret_cast.

As Reedbeta already pointed out (pardon the pun), arrays and pointers are actually the same thing. What he means by that is that when you do something like this:

int nums[1024];

You are actually creating a pointer to the first element in the array.

Not quite, there is no pointer, and &nums won’t do what you’d expect (it doesn’t return an int**, but rather an int(*)[1024]). The variable ‘nums’ can be (implicitely) converted to a pointer, but it isn’t the same as a pointer. There is no piece of memory that stores the pointer, which is why you can’t reassign it with a different pointer or have it’s address taken as a ‘pointer to pointer’.

However, if you use this declaration as a parameter for a function, then it *is* a pointer. Confusing, eh? B) (if you want a function to only accept arrays of 1024 elements, use int(&nums)[1024] as a parameter)

0efe53f7a0e80918b40990d256cb4fe1
0
KR3M3R 101 Jan 09, 2007 at 00:46

First, thanks for the help. I really appreciate it. Pointers are getting my head spinning and I’m still trying to get oriented.

I may have a follow up question in another day or so (while I process), but for now, I was wondering how often does a programmer actually use pointers and the like? When you’re employed as a programmer, is this something one is likely to come across or just something CS teachers like to torture students with?
-Robb

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 168 Jan 09, 2007 at 00:49

Oh, pointers are extremely common when programming in C++. There are other languages that don’t have pointers, but they have references, which are pretty much the same thing. So, it’s pretty vital to know pointers. Don’t worry, understanding pointers will become easier with time and experience - it’ll soon be second nature to you.

6cad28055d4af37574fe0d4064555e53
0
GroundKeeper 101 Jan 10, 2007 at 09:47

Teaching a course in any referencing/pointer capable language will confirm Reedbeta. In most high-level languages I feel this is a bigger problem for the beginner since they hide the referencing all together.

What would we do without our pointers! I makes code so beautiful. ;)

Cd577ee1cb56aa2ad5645b7daa0a2830
0
eddie 101 Jan 10, 2007 at 15:27

Not only does it make it beautiful, but it makes it make sense.

In real life, you don’t do “copy” semantics. If I’m talking about how many oranges you’re holding, I don’t go out and buy the same amount of oranges you have, just to count them. Instead I “point” to the ones you have, and count those.

It’s as valuable a paradigm as “looking up” what others properties are in real life.

(God bless overworked analogies)

860fe478a2545d6c07b88c759292499e
0
SmokingRope 101 Jan 18, 2007 at 01:10

As already shown pointers and arrays are similar.

char l_array[3]; EDIT: char *l_array = new char[3];
char *l_pointer = l_array;

And if you deal with c style strings you might end up looping through an array in just this way.
(Example 1)

for( l_pointer = l_array ; *l_pointer != 0 ; l_pointer++ )
{
    cout << *l_pointer;
}

This code will print the contents of the array, stopping when the null character ‘0’ is reached at the end.

You don’t want to use the array itself in this situation.

(Example2)

for( ; *l_array != 0 ; l_array++ )
{
    cout << *l_array;
}

In the code above, the contents of the array will still be printed. Note however, that the array itself will be pointing to the last element in the array and the rest of the contents of the array will be effectively lost.

In example 1 the pointer is assigned the address at which the array is also pointing to. At the end of each iteration of the loop, the pointer is then incremented by the size of one char, thus causing the pointer to ‘point at’ the next element in the array.

In example 2 there is no intermediary pointer. The array itself has been incremented by the size of one char and so now has a new first element. It would be possible then to address this array erroneously and write beyond the original array’s boundary through a statement such as:

l_array[1] = ‘i’;

Were this array created using the syntax:

char l_array[3];

these problems would not be present.

In cases such as the one shown above, and when the array would have been passed as a parameter, such as:

void someFunc( char pData[] )

It is still possible to encounter this error.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Jan 18, 2007 at 01:28

@SmokingRope

As already shown you can treat arrays and pointers the same.

No you can’t, read my reaction earlier in this thread.

You don’t want to use the array itself in this type of situation.

You don’t want to, but even if you did, you couldn’t ;)

for( ; *l_array != 0 ; l_array++ )
{
    cout << *l_array;
}

In the code above, the contents of the array will still be printed.

No, you will get a compile error, stating that l_array is not a modifiable lvalue (or something similar).

Additionally, the error present in example 2 can be a significant source of memory leaks and/or memory corruption.

How can a program that refuses to compile leak memory? ;)

One to never forget: arrays aren’t pointers, even though they have similar syntax.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Jan 18, 2007 at 01:42

Btw, check this educational (yet funny) video about pointers: http://cslibrary.stanford.edu/104/

860fe478a2545d6c07b88c759292499e
0
SmokingRope 101 Jan 18, 2007 at 01:52

I brought that on myself …
i had meant in terms of an array definition such as:

char *l_array = new char[3];

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Jan 18, 2007 at 01:58

Only in that piece of code l_array is not an array, but a pointer (that points to the first element of the newly allocated array) ;)

860fe478a2545d6c07b88c759292499e
0
SmokingRope 101 Jan 18, 2007 at 02:32

Although i have to agree with you, it’s still possible to address a pointer in ways such as l_array[1] which makes the distinction irrelevant.

They both can be accessed as an array, and they both refer to a block of memory which stores a contiguous series of elements of the same type.

You’re missing the point!

And i edited the post, for readability :surrender

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 168 Jan 18, 2007 at 09:16

The distinction’s not irrelevant; arrays and pointers are different things. It’s not true that a pointer necessarily refers to a block of memory storing contiguous elements of the same type. Also with arrays there is no memory location storing the address of the first element, so for instance you can’t take the address of the array, though you can take the address of a pointer. The fact that they both support subscripting, deferencing, and addition/subtraction doesn’t mean they are interchangeable.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Jan 18, 2007 at 10:43

SpreeTree: actually I think you’re the one missing the point ;). According to your reasoning, random access iterators are pointers as well as you can use the same syntax as with pointers (arithmetic, dereferecing, etc.). But they’re clearly not pointers, they’re just designed to behave like pointers (just like with arrays).
@Reedbeta

so for instance you can’t take the address of the array

Actually you can, and this yields a clear distinction with pointers:

int main()
{
    int array[10];
    int * ptr = array;

    std::cout << typeid(array).name() << std::endl; // outputs "int[10]"
    std::cout << typeid(ptr).name() << std::endl; // outputs "int*"

    int ** ptrToPtr = &ptr;
    int (*ptrToArrayOf10)[10] = &array;

    ptrToPtr[2][3] = 34;  // indexes the 3rd element, or ptrToPtr+2, which is an int*, then indexes the 4th element from that pointer
    ptrToArrayOf10[2][3]; // indexes the 3rd 10-element array (effectively array[20]), and then 3 elements next to that (array[23])

    ptrToPtr = new int*[10]; // allocates array of 10 pointers
    ptrToArrayOf10 = new int[20][10]; // allocates 200 ints consecutive in memory

    void foo1(int(&)[10]);
    void foo2(int*&);

    foo1(ptr); // compile error
    foo1(array); // ok

    foo2(ptr); // ok
    foo2(array); // compile error
}

Hey whatta ya know, they actually are different ;)

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 168 Jan 18, 2007 at 16:16

I stand corrected ;)