Pointer masters

Pages: 12
Hey everyone.
I study computer science.The degree is going well, but there is one module which scares me.C++.The problem is that my professor is obsessed with pointers.Every question must have a pointer.As a result, even if you know everything in c++, but you not excellent with pointers you may fail the module.From the first question to the last you see a pointer.

May you guys please help me.I need a book, article or anything that would make me master pointers.

Not: int x = 5;
int *p;
p=&x;
not those kind. Because he brings things like: foo**** p; pointer arithmetic etc. and clearly,they loose me at times.
Guys how did you master pointers, Any thing that could help me.

Regards
Guys how did you master pointers

I believe I mastered pointers when I finally realized that they are simply variables that hold a memory address, and their "type" just hints how to treat the data located at the memory address.

foo**** p; holds the memory address of a pointer to a pointer to a pointer of type foo.
But in the end it's still just a memory address.

As for pointer arithmetic, it's only different from "regular" arithmetic in that the type of the pointer affects the result.

Here's an article I wrote a while back:
http://www.cplusplus.com/articles/z186b7Xj/

And other possibly relevant links:
http://www.unixwiz.net/techtips/reading-cdecl.html
http://c-faq.com/ptrs/index.html
http://www.newty.de/fpt/index.html
I agree with Catfish4, pointers are simply variables that hold a memory address, that's all there is to know really... anyways, here's a book that explains pointers so well by the time you finish reading the chapter you should be fluent at using pointers:

http://www.amazon.co.uk/Jumping-into-C-Alex-Allain/dp/0988927802

and also check out page 63 here:
http://www.cplusplus.com/files/tutorial.pdf
Thanks a lot for the input guys, will try them out.Hopefully I would be as fluent with pointers as Marine suggest. Thanks again guys
@Catfish4
That article is reasonably good except that several of the examples use bad practices which could result in undefined behaviour; for example, several of your examples dereference pointers to memory that aren't necessarily owned by the program (e.g. v = i + 500; - the bounds of i are not known, so i + 500 may be an invalid address; float* pf = reinterpret_cast<float*>(100); - first of all, I don't know why you're using reinterpret_cast there, and second, the address 100 hasn't been stack- or heap-allocated so you can't use it; pf += 1; - this exceeds the bounds of pf which is undefined; also // force pf to contain the value 100 (0x64 in hexadecimal) is not what that cast is doing: it's actually setting pf to point to the address 0x64, and if you try to dereference it, you won't get a value, you'll get a segmentation fault).
Thanks for the feedback chrisname. Hopefully the OP will not mind if I reply to you in this thread.

several of your examples dereference pointers to memory that aren't necessarily owned by the program (e.g. v = i + 500; - the bounds of i are not known, so i + 500 may be an invalid address

I don't see where anything is dereferenced.
Also, it is irrelevant if the memory address is not safe to use, the purpose of the example is to show that pointers store an integer which is a memory address.

I don't know why you're using reinterpret_cast there

It doesn't compile without... or at least back then when I wrote the article it didn't.

// force pf to contain the value 100 (0x64 in hexadecimal) is not what that cast is doing: it's actually setting pf to point to the address 0x64

That's what the comment says, at least that's how I read it. I'm open to suggestions for rewording.

Having re-read the article, one problem I saw was that I did pointer arithmetic on a void pointer, which is Undefined Behavior in C although I don't know if the same is true for C++.
pointer arithmetic that moves a pointer outside of an array is undefined even without dereferencing.
Catfish4 wrote:
It doesn't compile without... or at least back then when I wrote the article it didn't.

It probably doesn't compile without the reinterpret_cast because you were trying to implicitly cast an integer to a pointer, which may result in undefined behaviour. Additionally, reinterpret_cast has runtime overhead and lacks compile-time safety. A static_cast should work, and lacks those disadvantages, although it could still lead to undefined behaviour.

That's what the comment says, at least that's how I read it. I'm open to suggestions for rewording.

I would say something along the lines of "cause it to point to the address 0x64" because "force it to contain" makes it sound like it stores it as a value.

Cubbi wrote:
pointer arithmetic that moves a pointer outside of an array is undefined even without dereferencing.

This. i might point to the end of addressable memory (not unlikely if it's a stack address) making i + 500 2,000 bytes (500 * sizeof(int)) beyond the address of memory on some platforms (and, depending on the size of i, causing an integer overflow to boot).
Last edited on
foo**** p;


Drop out now.
closed account (S6k9GNh0)
Nah, that's actually good practice. It's not potentially useful but helps with the concept of pointers.
Cubbi wrote:
pointer arithmetic that moves a pointer outside of an array is undefined even without dereferencing.

I am not sure I understand.
Do you imply that pointer arithmetic is undefined in the case of pointers not pointing within an array, but pointing to a single element?
And do you also imply that pointer arithmetic is undefined in the case of "bad" pointers?

As for UB when moving outside of an array, it makes me wonder how iterators incremented to vector::end() deal with this.

chrisname wrote:
A static_cast should work

Well, does it?

chrisname wrote:
I would say something along the lines of "cause it to point to the address 0x64" because "force it to contain" makes it sound like it stores it as a value.

I guess it might be clearer for the reader, to reword it your way.
Throughout the article I kept reiterating that a pointer's value is the memory address it contains, which is why I didn't think "force to contain" would be confusing.
Catfish4 wrote:
As for UB when moving outside of an array, it makes me wonder how iterators incremented to vector::end() deal with this.

Maybe the vector stores an extra element to represent the end. Although that would mean allocating sizeof(T) more data than is actually being used...
Do you imply that pointer arithmetic is undefined in the case of pointers not pointing within an array, but pointing to a single element?

No: pointer to an object that is not an element of an array is treated as a pointer to an element of an array of length 1 (for the purpose of pointer arithmetic)

And do you also imply that pointer arithmetic is undefined in the case of "bad" pointers?

Yes: both the input into operator+ and the result must point at the elements of an array (and it has to be the same array), or one past.

As for UB when moving outside of an array, it makes me wonder how iterators incremented to vector::end() deal with this.

Pointer one past the end of an array can be computed (but can't be dereferenced)
bookerb6 wrote:
As a result, even if you know everything in c++, but you not excellent with pointers you may fail the module.
Mark Twain wrote:
When I was a boy of fourteen, my father was so ignorant I could hardly stand to have the old man around. But when I got to be twenty-one, I was astonished by how much he'd learned in seven years.
Douglas Adams wrote:
Space is big. You just won't believe how vastly, hugely, mind- bogglingly big it is. I mean, you may think it's a long way down the road to the chemist's, but that's just peanuts to space.

C++ is big. You might now think that pointers are an annoying pebble on the road to chemist's, but everything in C++ might later turn out to be bigger, much bigger, than you know now, and that pointers are actually rather easy way to shoot your feet of compared to other beasts lurking within everything in C++.
If you want practice with pointers maybe try BrainFuck.

Here's a simple interpreter for it that I made a while back.

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>

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

    std::string code = "++++++++++[>+++++++>++++++++++>+++++++++++>+++++++++>+++>+<<<<<<-]>++.>+.>--..+++.>>++.<---.<.+++.------.<-.>>>+.>.";
    for( int i = 0; i < code.size(); ++i )
    {
        switch( code[i] )
        {
            case '<':
                --ptr;
                break;
            case '>':
                ++ptr;
                break;
            case '-':
                --*ptr;
                break;
            case '+':
                ++*ptr;
                break;
            case '.':
                std::cout << *ptr;
                break;
            case ',':
                std::cin >> *ptr;
                break;
            case '[':
                if( !*ptr )
                {
                    while( code[i] != ']' )
                        ++i;
                }
                break;
            case ']':
                if( *ptr )
                {
                    while( code[i] != '[' )
                        --i;
                }
                break;
        }
    }
}
Hello World!
> Additionally, reinterpret_cast has runtime overhead
¿really?

http://www.cplusplus.com/doc/tutorial/typecasting/
reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes. The operation result is a simple binary copy of the value from one pointer to the other

> A static_cast should work, and lacks those disadvantages
static_cast can perform conversions between pointers to related classes,


dynamic_cast is the one that performs runtime checks
@ne555
Oops, you're right, my mistake.
closed account (S6k9GNh0)
Rule of thumb: If you're using reinterpret_cast... you're doing it wrong. :D
closed account (N36fSL3A)
computerquip wrote:
Rule of thumb: If you're using reinterpret_cast... you're doing it wrong. :D
Sometimes you want to convert something directly into another value...

such as:
(Uint8s are unsigned chars)
1
2
3
float dec = 1.23;

Uint8* floating_pnt = reinterpret_cast<Uint8*>(&dec);
Last edited on
Pages: 12