What are the barriers to understanding pointers and what can be done to overcome them? [closed]
Asked Answered
M

28

470

Why are pointers such a leading factor of confusion for many new, and even old, college-level students in C or C++? Are there any tools or thought processes that helped you understand how pointers work at the variable, function, and beyond level?

What are some good practice things that can be done to bring somebody to the level of, "Ah-hah, I got it," without getting them bogged down in the overall concept? Basically, drill-like scenarios.

Microelectronics answered 8/8, 2008 at 6:18 Comment(7)
#1433463Decide
The thesis of this question is that pointers are hard to understand. The question offers no evidence that pointers are any harder to understand than anything else.Nagoya
Maybe I'm missing something (because I code in GCC'd languages) but I always thought if pointers in memory as a Key->Value structure. Since it's expensive to pass around large amounts of data in a program, you create the structure (value) and pass around it's pointer/reference (key) because the key is a much smaller representation of the larger structure. The hard part is when you need to compare two pointers/references (are you comparing the keys or the values) which requires more work to break into the data contained within the structure (value).Minus
What I find confusing is that pointers have a type. It seems to me a memory in address will always be an int. Actually, the pointer's type is the type of the var the pointer points to.... The logic it takes to digest a block of text like that goes beyond what people see in casual, daily reading.Fireweed
@Wolfpack'08 " It seems to me a memory in address will always be an int." -- Then it should seem to you that nothing has a type, since they are all just bits in memory. "Actually, the pointer's type is the type of the var the pointer points to" -- No, the pointer's type is pointer to the type of the var the pointer points to -- which is natural and should be obvious.Lorrin
I always wondered what's so hard to grasp in the fact that variables (and functions) are just blocks of memory and pointers are variables storing memory addresses. This maybe too practical thought model might not impress all the fans of abstract concepts, but it perfectly helps to understand how pointers work.Hausmann
In a nutshell, students probably do not understand because they do not understand correctly, or at all, how a computer's memory in general, and specifically the C "memory model" works. This book Programming from the Ground Up gives a very good lesson on these topics.Brandeebranden
G
757

Pointers is a concept that for many can be confusing at first, in particular when it comes to copying pointer values around and still referencing the same memory block.

I've found that the best analogy is to consider the pointer as a piece of paper with a house address on it, and the memory block it references as the actual house. All sorts of operations can thus be easily explained.

I've added some Delphi code down below, and some comments where appropriate. I chose Delphi since my other main programming language, C#, does not exhibit things like memory leaks in the same way.

If you only wish to learn the high-level concept of pointers, then you should ignore the parts labelled "Memory layout" in the explanation below. They are intended to give examples of what memory could look like after operations, but they are more low-level in nature. However, in order to accurately explain how buffer overruns really work, it was important that I added these diagrams.

Disclaimer: For all intents and purposes, this explanation and the example memory layouts are vastly simplified. There's more overhead and a lot more details you would need to know if you need to deal with memory on a low-level basis. However, for the intents of explaining memory and pointers, it is accurate enough.


Let's assume the THouse class used below looks like this:

type
    THouse = class
    private
        FName : array[0..9] of Char;
    public
        constructor Create(name: PChar);
    end;

When you initialize the house object, the name given to the constructor is copied into the private field FName. There is a reason it is defined as a fixed-size array.

In memory, there will be some overhead associated with the house allocation, I'll illustrate this below like this:

---[ttttNNNNNNNNNN]---
     ^   ^
     |   |
     |   +- the FName array
     |
     +- overhead

The "tttt" area is overhead, there will typically be more of this for various types of runtimes and languages, like 8 or 12 bytes. It is imperative that whatever values are stored in this area never gets changed by anything other than the memory allocator or the core system routines, or you risk crashing the program.


Allocate memory

Get an entrepreneur to build your house, and give you the address to the house. In contrast to the real world, memory allocation cannot be told where to allocate, but will find a suitable spot with enough room, and report back the address to the allocated memory.

In other words, the entrepreneur will choose the spot.

THouse.Create('My house');

Memory layout:

---[ttttNNNNNNNNNN]---
    1234My house

Keep a variable with the address

Write the address to your new house down on a piece of paper. This paper will serve as your reference to your house. Without this piece of paper, you're lost, and cannot find the house, unless you're already in it.

var
    h: THouse;
begin
    h := THouse.Create('My house');
    ...

Memory layout:

    h
    v
---[ttttNNNNNNNNNN]---
    1234My house

Copy pointer value

Just write the address on a new piece of paper. You now have two pieces of paper that will get you to the same house, not two separate houses. Any attempts to follow the address from one paper and rearrange the furniture at that house will make it seem that the other house has been modified in the same manner, unless you can explicitly detect that it's actually just one house.

Note This is usually the concept that I have the most problem explaining to people, two pointers does not mean two objects or memory blocks.

var
    h1, h2: THouse;
begin
    h1 := THouse.Create('My house');
    h2 := h1; // copies the address, not the house
    ...
    h1
    v
---[ttttNNNNNNNNNN]---
    1234My house
    ^
    h2

Freeing the memory

Demolish the house. You can then later on reuse the paper for a new address if you so wish, or clear it to forget the address to the house that no longer exists.

var
    h: THouse;
begin
    h := THouse.Create('My house');
    ...
    h.Free;
    h := nil;

Here I first construct the house, and get hold of its address. Then I do something to the house (use it, the ... code, left as an exercise for the reader), and then I free it. Lastly I clear the address from my variable.

Memory layout:

    h                        <--+
    v                           +- before free
---[ttttNNNNNNNNNN]---          |
    1234My house             <--+

    h (now points nowhere)   <--+
                                +- after free
----------------------          | (note, memory might still
    xx34My house             <--+  contain some data)

Dangling pointers

You tell your entrepreneur to destroy the house, but you forget to erase the address from your piece of paper. When later on you look at the piece of paper, you've forgotten that the house is no longer there, and goes to visit it, with failed results (see also the part about an invalid reference below).

var
    h: THouse;
begin
    h := THouse.Create('My house');
    ...
    h.Free;
    ... // forgot to clear h here
    h.OpenFrontDoor; // will most likely fail

Using h after the call to .Free might work, but that is just pure luck. Most likely it will fail, at a customers place, in the middle of a critical operation.

    h                        <--+
    v                           +- before free
---[ttttNNNNNNNNNN]---          |
    1234My house             <--+

    h                        <--+
    v                           +- after free
----------------------          |
    xx34My house             <--+

As you can see, h still points to the remnants of the data in memory, but since it might not be complete, using it as before might fail.


Memory leak

You lose the piece of paper and cannot find the house. The house is still standing somewhere though, and when you later on want to construct a new house, you cannot reuse that spot.

var
    h: THouse;
begin
    h := THouse.Create('My house');
    h := THouse.Create('My house'); // uh-oh, what happened to our first house?
    ...
    h.Free;
    h := nil;

Here we overwrote the contents of the h variable with the address of a new house, but the old one is still standing... somewhere. After this code, there is no way to reach that house, and it will be left standing. In other words, the allocated memory will stay allocated until the application closes, at which point the operating system will tear it down.

Memory layout after first allocation:

    h
    v
---[ttttNNNNNNNNNN]---
    1234My house

Memory layout after second allocation:

                       h
                       v
---[ttttNNNNNNNNNN]---[ttttNNNNNNNNNN]
    1234My house       5678My house

A more common way to get this method is just to forget to free something, instead of overwriting it as above. In Delphi terms, this will occur with the following method:

procedure OpenTheFrontDoorOfANewHouse;
var
    h: THouse;
begin
    h := THouse.Create('My house');
    h.OpenFrontDoor;
    // uh-oh, no .Free here, where does the address go?
end;

After this method has executed, there's no place in our variables that the address to the house exists, but the house is still out there.

Memory layout:

    h                        <--+
    v                           +- before losing pointer
---[ttttNNNNNNNNNN]---          |
    1234My house             <--+

    h (now points nowhere)   <--+
                                +- after losing pointer
---[ttttNNNNNNNNNN]---          |
    1234My house             <--+

As you can see, the old data is left intact in memory, and will not be reused by the memory allocator. The allocator keeps track of which areas of memory has been used, and will not reuse them unless you free it.


Freeing the memory but keeping a (now invalid) reference

Demolish the house, erase one of the pieces of paper but you also have another piece of paper with the old address on it, when you go to the address, you won't find a house, but you might find something that resembles the ruins of one.

Perhaps you will even find a house, but it is not the house you were originally given the address to, and thus any attempts to use it as though it belongs to you might fail horribly.

Sometimes you might even find that a neighbouring address has a rather big house set up on it that occupies three address (Main Street 1-3), and your address goes to the middle of the house. Any attempts to treat that part of the large 3-address house as a single small house might also fail horribly.

var
    h1, h2: THouse;
begin
    h1 := THouse.Create('My house');
    h2 := h1; // copies the address, not the house
    ...
    h1.Free;
    h1 := nil;
    h2.OpenFrontDoor; // uh-oh, what happened to our house?

Here the house was torn down, through the reference in h1, and while h1 was cleared as well, h2 still has the old, out-of-date, address. Access to the house that is no longer standing might or might not work.

This is a variation of the dangling pointer above. See its memory layout.


Buffer overrun

You move more stuff into the house than you can possibly fit, spilling into the neighbours house or yard. When the owner of that neighbouring house later on comes home, he'll find all sorts of things he'll consider his own.

This is the reason I chose a fixed-size array. To set the stage, assume that the second house we allocate will, for some reason, be placed before the first one in memory. In other words, the second house will have a lower address than the first one. Also, they're allocated right next to each other.

Thus, this code:

var
    h1, h2: THouse;
begin
    h1 := THouse.Create('My house');
    h2 := THouse.Create('My other house somewhere');
                         ^-----------------------^
                          longer than 10 characters
                         0123456789 <-- 10 characters

Memory layout after first allocation:

                        h1
                        v
-----------------------[ttttNNNNNNNNNN]
                        5678My house

Memory layout after second allocation:

    h2                  h1
    v                   v
---[ttttNNNNNNNNNN]----[ttttNNNNNNNNNN]
    1234My other house somewhereouse
                        ^---+--^
                            |
                            +- overwritten

The part that will most often cause crash is when you overwrite important parts of the data you stored that really should not be randomly changed. For instance it might not be a problem that parts of the name of the h1-house was changed, in terms of crashing the program, but overwriting the overhead of the object will most likely crash when you try to use the broken object, as will overwriting links that is stored to other objects in the object.


Linked lists

When you follow an address on a piece of paper, you get to a house, and at that house there is another piece of paper with a new address on it, for the next house in the chain, and so on.

var
    h1, h2: THouse;
begin
    h1 := THouse.Create('Home');
    h2 := THouse.Create('Cabin');
    h1.NextHouse := h2;

Here we create a link from our home house to our cabin. We can follow the chain until a house has no NextHouse reference, which means it's the last one. To visit all our houses, we could use the following code:

var
    h1, h2: THouse;
    h: THouse;
begin
    h1 := THouse.Create('Home');
    h2 := THouse.Create('Cabin');
    h1.NextHouse := h2;
    ...
    h := h1;
    while h <> nil do
    begin
        h.LockAllDoors;
        h.CloseAllWindows;
        h := h.NextHouse;
    end;

Memory layout (added NextHouse as a link in the object, noted with the four LLLL's in the below diagram):

    h1                      h2
    v                       v
---[ttttNNNNNNNNNNLLLL]----[ttttNNNNNNNNNNLLLL]
    1234Home       +        5678Cabin      +
                   |        ^              |
                   +--------+              * (no link)

In basic terms, what is a memory address?

A memory address is in basic terms just a number. If you think of memory as a big array of bytes, the very first byte has the address 0, the next one the address 1 and so on upwards. This is simplified, but good enough.

So this memory layout:

    h1                 h2
    v                  v
---[ttttNNNNNNNNNN]---[ttttNNNNNNNNNN]
    1234My house       5678My house

Might have these two address (the leftmost - is address 0):

  • h1 = 4
  • h2 = 23

Which means that our linked list above might actuall look like this:

    h1 (=4)                 h2 (=28)
    v                       v
---[ttttNNNNNNNNNNLLLL]----[ttttNNNNNNNNNNLLLL]
    1234Home      0028      5678Cabin     0000
                   |        ^              |
                   +--------+              * (no link)

It is typical to store an address that "points nowhere" as a zero-address.


In basic terms, what is a pointer?

A pointer is just a variable holding a memory address. You can typically ask the programming language to give you its number, but most programming languages and runtimes tries to hide the fact that there is a number beneath, just because the number itself does not really hold any meaning to you. It is best to think of a pointer as a black box, ie. you don't really know or care about how it is actually implemented, just as long as it works.

Glacialist answered 8/8, 2008 at 6:18 Comment(26)
This is a nice explanation of the concept, sure. The concept is NOT the thing that I find confusing about pointers though, so this whole essay was a bit wasted.Kurtiskurtosis
But just to have asked, what do you find confusing about pointers?Glacialist
Under "Freeing the memory", wouldn't you only "erase the address from your paper" after also setting your pointer to null? Otherwise, you're still pointing to memory location of deallocated memory (dangling pointer)Koby
No, the contents of the paper is the pointer value, so when you erase it, you set it to null, but I didn't go into that level of detail in this post.Glacialist
I've revisited this post several times since you wrote the answer. Your clarification with code is excellent, and I appreciate you revisiting it to add/refine more thoughts. Bravo Lasse!Microelectronics
+1 very nice. I used for a long time the similar analogy to explain messaging, services and queues (service name => the address on envelope, queue => the mailbox in front of house etc) so the address on paper/house resonated a chord with me :)Barbarese
Pointers to pointers: Note that says that the address is written on a note that you have in your left front jeans pocket. Operators are hard. In C & is writing a note. * is reading a note and following the instructions to find the house. * is also used in type declarations, which confuses people even more. What to do with pointers vs arrays with this analogy? A note that mentions the first home on the street and an understanding that you actually meant the whole street when you were writing this note.Guam
Very nice answer. Just one comment for "Allocate memory". Some alloc methods such as VirtualAlloc on Win32 does allow you to specify the address of the allocation, but its not the common case to do so.Souvaine
Added diagrams of how memory could look after allocation, freeing, etc. with proper explanations. This also allowed me to illustrate the effects of buffer overruns and to give a proper (simplified) explanation of what a pointer really is at the end. Also fixed some typos. This also brought the answer into wiki-mode, which is just as well, at this point it isn't meant to be a rep-farm.Glacialist
@Lasse +1 I wish I could upvote more. This is the best/most-detailed answer I have seen on SO so far. It turns out that I know more about pointers than I thought I did because they act the same as references in C# (except C# does garbage collection and the compiler won't let you overflow fixed-size arrays).Minus
@Lasse Two things: First, are the pointers stored on the stack and therefore disposed when they fall out of scope and; Two, would it be worth it to add an example of cloning in your answer. I'm not sure how it's done in C but it's a pretty common question that a lot of primarily C# developers (including me) struggle to grasp when they start learning the intricacies of references.Minus
Cloning is a difficult subject, and I am loath to change this answer into also covering references in a managed garbage-collected environment. Perhaps it would be best served with a separate answer or even question? I'm open to suggestions however (also, anyone with enough rep is free to edit the answer as well.)Glacialist
@Lasse Please forgive my ignorance of C. I meant it in a C context not a C# GCed environment. How would you 'clone' an object in C (IE, create a new object copy of the data)? Ex. H2 = H1 where H2 is a completely new object with contents identical to H1, not just a reference pointing to H1.Minus
If h1 and h2 are pointers, memcpy( h2, h1, sizeof(struct house) ) opengroup.org/onlinepubs/007908799/xsh/memcpy.htmlGallows
This explanation is 50x more complex than it needs to be. But great effort man. We need more enthusiastic responders like yourself.Butternut
I do not understand how "Freeing the memory but keeping a (now invalid) reference" is different from (or even a "variation" of) "Dangling pointers"? In both cases, there is a pointer to a location that has already been freed.Noyes
This answer is good for what it is, but because it is not in case, it naturally skips over the important detail of syntax. Most errors are syntax errors, so the most important thing can be said to have been skipped. I am always puzzled at why an ampersand or asterisk is used, and how neither seems to reference one or the other, how arrays work with pointers, etc.Fireweed
This explanation does not take into account the fact that pointers usually themselves occupy memory and can be pointed to.Farceur
There is no way a single page of text (no matter how long it is) can sum up every nuance of memory management, references, pointers, etc. Since 465 people have voted this up, I'd say it serves as a good enough starting page on the information. Is there more to learn? Sure, when is it not?Glacialist
Great and the best, but would have been more awesome if you could have used C or C++ as asked in question.Ezechiel
I am not qualified to write correct C/C++ code. The code was added later after a lot of pressure to show some code relevant to the answer.Glacialist
For sake of completeness, we might want to add links for further learning. Link to the difference between pointer and reference would be a good start.Smashandgrab
So, the way to have a safe copy of the 'house address' is not to copy this address (h2 := h1) but have a pointer to the first pointer ?Sikorsky
Back in the early '80's, the AHA moment for me was the realization that pointers and dynamic memory allocation are NOT synonymous. Pascal's pointer syntax was used exclusively with dynamic memory allocation/freeing. However, C's pointer syntax was independent of dynamic memory (e.g. you can take the address of an auto variable and pass it as a pointer as a parameter into a function, and use pointers without ever doing a malloc or free). Once I saw it in C, the AHA occurred, and the Pascal pointer semantics ALSO became clearer.Downhaul
@Boctulus No, that's simply two different operations, both of which have legitimate uses. Neither is inherently safer. Pointer to a pointer is just another layer of indirection.Woden
You may want to give the reader a really bad memory who cannot remember anything without having the piece of paper in hand or being in the house.Ogilvie
C
158

In my first Comp Sci class, we did the following exercise. Granted, this was a lecture hall with roughly 200 students in it...

Professor writes on the board: int john;

John stands up

Professor writes: int *sally = &john;

Sally stands up, points at john

Professor: int *bill = sally;

Bill stands up, points at John

Professor: int sam;

Sam stands up

Professor: bill = &sam;

Bill now points to Sam.

I think you get the idea. I think we spent about an hour doing this, until we went over the basics of pointer assignment.

Chiron answered 8/8, 2008 at 6:18 Comment(9)
I don't think I got it wrong. My intention was to change the value of the pointed-to variable from John to Sam. It's a little harder to represent with people, because it looks like you're changing the value of both pointers.Chiron
But the reason it's confusing though is that it's not like john got up from his seat and then sam sat down, as we might imagine. It's more like sam came over and stuck his hand into john and cloned the sam programming into john's body, like hugo weaving in matrix reloaded.Kurtiskurtosis
More like Sam takes John's seat, and John floats around the room until he bumps into something critical and causes a segfault.Contrasty
I personally find this example unnecessarily complicated. My prof told me to point at a light and said "your hand is the pointer to the light object".Warmhearted
The problem with this type of examples is that pointer to X and X are not the same. And this doesn't get portrayed with people.Oria
this was really wonderful...I like it...but I'm concerned with the pointers themselves are to be optimized, since they virtually occupy a memory block to hold the address...Joaniejoann
@armin John doesn't represent an integer; then he would be a pointer. Instead, he is an integer.Ferminafermion
@Ferminafermion To be more precise: John and Sam are persons, but here - in this exercise - they try to represent something else. And if we look at the code, we could say John stands for the uninitialized variable "John" of type "int". Or if we think about runtime, we could say he stands for a specific storage space full of garbage. Point is, this whole exercise doesn't help people understand what's really going on. Just look at all the different interpretations.Voss
I don't understand why "Sally should not point to John after the sequence". Because, bill and sally are two different pointers. if value of bill changes, why Sally should change?Ajaajaccio
O
131

An analogy I've found helpful for explaining pointers is hyperlinks. Most people can understand that a link on a web page 'points' to another page on the internet, and if you can copy & paste that hyperlink then they will both point to the same original web page. If you go and edit that original page, then follow either of those links (pointers) you'll get that new updated page.

Overmodest answered 8/8, 2008 at 6:18 Comment(6)
I really like this. It's not hard to see that writing out a hyperlink twice does not make two websites appear (just like int *a = b does not make two copies of *b).Fusion
This is actually very intuitive and something everyone should be able to relate to. Although there are a lot of scenarios where this analogy falls apart. Great for a quick introduction though. +1Jasso
A link to a page being opened up twice usually creates two almost entirely independent instances of that webpage. I think an hyperlink could rather be a good analogy to a constructor maybe, but not to a pointer.Goethite
@ThoAppelsin Not necessarily true, if you're accessing a static html webpage for example, you're accessing a single file on the server.Snashall
@RespectMyAuthoritah Still true. Your computer downloads the information required to construct that web page from its server, then your browser does its magic. You receive the full copy of whatever required. Think about it like this: Even if you lose connection, once you have opened up that web page, you won't lose it, until you get rid of it. This analogy is almost entirely false; and it rather is a good analogy for how, for example, when a structure itself is passed as an argument to a function, the function receives a full copy into its variable parameter.Goethite
You're overthinking it. The hyperlinks point to files on the server, that's the extent of the analogy.Snashall
A
49

The reason pointers seem to confuse so many people is that they mostly come with little or no background in computer architecture. Since many don't seem to have an idea of how computers (the machine) is actually implemented - working in C/C++ seems alien.

A drill is to ask them to implement a simple bytecode based virtual machine (in any language they chose, python works great for this) with an instruction set focussed on pointer operations (load, store, direct/indirect addressing). Then ask them to write simple programs for that instruction set.

Anything requiring slightly more than simple addition is going to involve pointers and they are sure to get it.

Aquarium answered 8/8, 2008 at 6:18 Comment(7)
Interesting. No idea how to start going about this though. Any resources to share?Detect
I agree. For example, I learned to program in assembly before C and knowing how registers work, learning pointers was easy. In fact, there wasn't much learning, it all came very natural.Contravention
Take a basic CPU, say something that runs lawnmowers or dish washers and implement it. Or a very very basic subset of ARM or MIPS. Both of those have a very simple ISA.Fancyfree
It might be worth pointing out that this educational approach has been advocated/practiced by Donald Knuth himself. Knuth's Art of Computer Programming describes a simple hypothetical architecture and asks students to implement solutions to practice problems in a hypothetical assembly language for that architecture. Once it became practically feasible, some students reading Knuth's books actually implement his architecture as a VM (or use an existing implementation), and actually run their solutions. IMO this is a great way to learn, if you have the time.Ballroom
I have always agreed with this, and I believe it is why I had no difficulty grasping pointers; since I learned to program with assembly way before I studied C pointers.Awed
@Awed I don't think it's that easy to understand people who simply can't grasp pointers (or, to be more exact, indirection in general). You're basically assuming that people who don't understand pointers in C would be able to start learning assembly, understand the underlying architecture of the computer and return to C with an understanding of pointers. This may be true for many, but according to some studies, it seems that some people inherently can't grasp indirection, even in principle (I still find that very hard to believe, but perhaps I've just been lucky with my "students").Woden
@Woden With the number of people I've encountered who simply cannot comprehend abstraction, be it in programming or even in real life, it doesn't surprise me at all that so many struggle with the notion of indirection! After all, they're not completely dissimilar.Lapith
F
28

Why are pointers such a leading factor of confusion for many new, and even old, college level students in the C/C++ language?

The concept of a placeholder for a value - variables - maps onto something we're taught in school - algebra. There isn't an existing parallel you can draw without understanding how memory is physically laid out within a computer, and no one thinks about this kind of thing until they're dealing with low level things - at the C/C++/byte communications level.

Are there any tools or thought processes that helped you understand how pointers work at the variable, function, and beyond level?

Addresses boxes. I remember when I was learning to program BASIC into microcomputers, there were these pretty books with games in them, and sometimes you had to poke values into particular addresses. They had a picture of a bunch of boxes, incrementally labelled with 0, 1, 2... and it was explained that only one small thing (a byte) could fit in these boxes, and there were a lot of them - some computers had as many as 65535! They were next to each other, and they all had an address.

What are some good practice things that can be done to bring somebody to the level of, "Ah-hah, I got it," without getting them bogged down in the overall concept? Basically, drill like scenarios.

For a drill? Make a struct:

struct {
char a;
char b;
char c;
char d;
} mystruct;
mystruct.a = 'r';
mystruct.b = 's';
mystruct.c = 't';
mystruct.d = 'u';

char* my_pointer;
my_pointer = &mystruct.b;
cout << 'Start: my_pointer = ' << *my_pointer << endl;
my_pointer++;
cout << 'After: my_pointer = ' << *my_pointer << endl;
my_pointer = &mystruct.a;
cout << 'Then: my_pointer = ' << *my_pointer << endl;
my_pointer = my_pointer + 3;
cout << 'End: my_pointer = ' << *my_pointer << endl;

Same example as above, except in C:

// Same example as above, except in C:
struct {
    char a;
    char b;
    char c;
    char d;
} mystruct;

mystruct.a = 'r';
mystruct.b = 's';
mystruct.c = 't';
mystruct.d = 'u';

char* my_pointer;
my_pointer = &mystruct.b;

printf("Start: my_pointer = %c\n", *my_pointer);
my_pointer++;
printf("After: my_pointer = %c\n", *my_pointer);
my_pointer = &mystruct.a;
printf("Then: my_pointer = %c\n", *my_pointer);
my_pointer = my_pointer + 3;
printf("End: my_pointer = %c\n", *my_pointer);

Output:

Start: my_pointer = s
After: my_pointer = t
Then: my_pointer = r
End: my_pointer = u

Perhaps that explains some of the basics through example?

Fight answered 8/8, 2008 at 6:18 Comment(2)
+1 for "without understanding how memory is physically laid". I came to C from an assembly language background and the concept of pointers was very natural and easy; and I've seen people with only a higher level language background struggle to figure it out. To make it worse the syntax is confusing (function pointers!), so learning the concept and the syntax at the same time is a recipe for trouble.Runnel
Yeah, it's similar to algebra (although algebra's have an extra understandability point in having their "variables" immutable). But about half the people I know have no grasp of algebra in practice. It just doesn't compute for them. They know all those "equations" and prescriptions to get to the result, but they apply them somewhat randomly, and clumsily. And they can't extend them for their own purpose - it's just some unchangeable, uncomposeable black box for them. If you understand algebra, and are able to use it effectively, you're already way ahead of the pack - even among programmers.Woden
V
25

The reason I had a hard time understanding pointers, at first, is that many explanations include a lot of rubbish about passing by reference. All this does is confuse the issue. When you use a pointer parameter, you're still passing by value; but the value happens to be an address rather than, say, an int.

Someone else has already linked to this tutorial, but I can highlight the moment when I began to understand pointers:

A Tutorial on Pointers and Arrays in C: Chapter 3 - Pointers and Strings

int puts(const char *s);

For the moment, ignore the const. The parameter passed to puts() is a pointer, that is the value of a pointer (since all parameters in C are passed by value), and the value of a pointer is the address to which it points, or, simply, an address. Thus when we write puts(strA); as we have seen, we are passing the address of strA[0].

The moment I read these words, the clouds parted and a beam of sunlight enveloped me with pointer understanding.

Even if you're a VB .NET or C# developer (as I am) and never use unsafe code, it's still worth understanding how pointers work, or you won't understand how object references work. Then you'll have the common-but-mistaken notion that passing an object reference to a method copies the object.

Vicegerent answered 8/8, 2008 at 6:18 Comment(0)
T
19

I found Ted Jensen's "Tutorial on Pointers and Arrays in C" an excellent resource for learning about pointers. It is divided into 10 lessons, beginning with an explanation of what pointers are (and what they're for) and finishing with function pointers. http://web.archive.org/web/20181011221220/http://home.netcom.com:80/~tjensen/ptr/cpoint.htm

Moving on from there, Beej's Guide to Network Programming teaches the Unix sockets API, from which you can begin to do really fun things. http://beej.us/guide/bgnet/

Tailgate answered 8/8, 2008 at 6:18 Comment(0)
K
12

The complexities of pointers go beyond what we can easily teach. Having students point to each other and using pieces of paper with house addresses are both great learning tools. They do a great job of introducing the basic concepts. Indeed, learning the basic concepts is vital to successfully using pointers. However, in production code, it's common to get into much more complex scenarios than these simple demonstrations can encapsulate.

I've been involved with systems where we had structures pointing to other structures pointing to other structures. Some of those structures also contained embedded structures (rather than pointers to additional structures). This is where pointers get really confusing. If you've got multiple levels of indirection, and you start ending up with code like this:

widget->wazzle.fizzle = fazzle.foozle->wazzle;

it can get confusing really quickly (imagine a lot more lines, and potentially more levels). Throw in arrays of pointers, and node to node pointers (trees, linked lists) and it gets worse still. I've seen some really good developers get lost once they started working on such systems, even developers who understood the basics really well.

Complex structures of pointers don't necessarily indicate poor coding, either (though they can). Composition is a vital piece of good object-oriented programming, and in languages with raw pointers, it will inevitably lead to multi-layered indirection. Further, systems often need to use third-party libraries with structures which don't match each other in style or technique. In situations like that, complexity is naturally going to arise (though certainly, we should fight it as much as possible).

I think the best thing colleges can do to help students learn pointers is to to use good demonstrations, combined with projects that require pointer use. One difficult project will do more for pointer understanding than a thousand demonstrations. Demonstrations can get you a shallow understanding, but to deeply grasp pointers, you have to really use them.

Kit answered 8/8, 2008 at 6:18 Comment(0)
A
10

I thought I'd add an analogy to this list that I found very helpful when explaining pointers (back in the day) as a Computer Science Tutor; first, let's:


Set the stage:

Consider a parking lot with 3 spaces, these spaces are numbered:

-------------------
|     |     |     |
|  1  |  2  |  3  |
|     |     |     |

In a way, this is like memory locations, they are sequential and contiguous.. sort of like an array. Right now there are no cars in them so it's like an empty array (parking_lot[3] = {0}).


Add the data

A parking lot never stays empty for long... if it did it would be pointless and no one would build any. So let's say as the day moves on the lot fills up with 3 cars, a blue car, a red car, and a green car:

   1     2     3
-------------------
| o=o | o=o | o=o |
| |B| | |R| | |G| |
| o-o | o-o | o-o |

These cars are all the same type (car) so one way to think of this is that our cars are some sort of data (say an int) but they have different values (blue, red, green; that could be an color enum)


Enter the pointer

Now if I take you into this parking lot, and ask you to find me a blue car, you extend one finger and use it to point to a blue car in spot 1. This is like taking a pointer and assigning it to a memory address (int *finger = parking_lot)

Your finger (the pointer) is not the answer to my question. Looking at your finger tells me nothing, but if I look where you're finger is pointing to (dereferencing the pointer), I can find the car (the data) I was looking for.


Reassigning the pointer

Now I can ask you to find a red car instead and you can redirect your finger to a new car. Now your pointer (the same one as before) is showing me new data (the parking spot where the red car can be found) of the same type (the car).

The pointer hasn't physically changed, it's still your finger, just the data it was showing me changed. (the "parking spot" address)


Double pointers (or a pointer to a pointer)

This works with more than one pointer as well. I can ask where is the pointer, which is pointing to the red car and you can use your other hand and point with a finger to the first finger. (this is like int **finger_two = &finger)

Now if I want to know where the blue car is I can follow the first finger's direction to the second finger, to the car (the data).


The dangling pointer

Now let's say you're feeling very much like a statue, and you want to hold your hand pointing at the red car indefinitely. What if that red car drives away?

   1     2     3
-------------------
| o=o |     | o=o |
| |B| |     | |G| |
| o-o |     | o-o |

Your pointer is still pointing to where the red car was but is no longer. Let's say a new car pulls in there... a Orange car. Now if I ask you again, "where is the red car", you're still pointing there, but now you're wrong. That's not an red car, that's orange.


Pointer arithmetic

Ok, so you're still pointing at the second parking spot (now occupied by the Orange car)

   1     2     3
-------------------
| o=o | o=o | o=o |
| |B| | |O| | |G| |
| o-o | o-o | o-o |

Well I have a new question now... I want to know the color of the car in the next parking spot. You can see you're pointing at spot 2, so you just add 1 and you're pointing at the next spot. (finger+1), now since I wanted to know what the data was there, you have to check that spot (not just the finger) so you can deference the pointer (*(finger+1)) to see there is a green car present there (the data at that location)

Apocopate answered 8/8, 2008 at 6:18 Comment(5)
Just don't use the word "double pointer". Pointers can point to anything, so obviously you can have pointers pointing to other pointers. They are not double pointers.Corelli
I think this misses the point that the “fingers” themselves, to continue your analogy, each “occupy a parking spot”. I'm not sure that people have any difficulty understanding pointers at the high level of abstraction of your analogy, it's understanding that pointers are mutable things that occupy memory locations, and how this is useful, that seems to evade people.Corrigendum
@Corrigendum - I do not disagree that there is a lot more one could go into WRT pointers, but I read the question: "without getting them bogged down in the overall concept" as a high level understanding. And to your point: "I'm not sure that people have any difficulty understanding pointers at the high level of abstraction" - you would be very surprised how many people do not understand pointers even to this levelApocopate
Is there any merit to extending the car-finger analogy to a person (with one or more fingers - and a genetic abnormality that can allow each of those to point in any direction!) sat in one of the cars pointing at another car (or bent over pointing at the wasteland beside the lot as an "uninitialised pointer"; or a whole hand splayed out pointing at a row of spaces as an "fixed size [5] array of pointers" or curled over into the palm "null pointer" that points to somewhere where it is known that there is NEVER a car)... 8-)Clamorous
typo: your* fingerSheen
S
10

I don't think pointers as a concept are particularly tricky - most students' mental models map to something like this and some quick box sketches can help.

The difficulty, at least that which I've experienced in the past and seen others deal with, is that the management of pointers in C/C++ can be unncessarily convoluted.

Shaylashaylah answered 8/8, 2008 at 6:18 Comment(0)
C
9

An example of a tutorial with a good set of diagrams helps greatly with the understanding of pointers.

Joel Spolsky makes some good points about understanding pointers in his Guerrilla Guide to Interviewing article:

For some reason most people seem to be born without the part of the brain that understands pointers. This is an aptitude thing, not a skill thing – it requires a complex form of doubly-indirected thinking that some people just can't do.

Commissariat answered 8/8, 2008 at 6:18 Comment(0)
B
8

I think the main barrier to understanding pointers is bad teachers.

Almost everyone are taught lies about pointers: That they are nothing more than memory addresses, or that they allow you to point to arbitrary locations.

And of course that they are difficult to understand, dangerous and semi-magical.

None of which is true. Pointers are actually fairly simple concepts, as long as you stick to what the C++ language has to say about them and don't imbue them with attributes that "usually" turn out to work in practice, but nevertheless aren't guaranteed by the language, and so aren't part of the actual concept of a pointer.

I tried to write up an explanation of this a few months ago in this blog post -- hopefully it'll help someone.

(Note, before anyone gets pedantic on me, yes, the C++ standard does say that pointers represent memory addresses. But it does not say that "pointers are memory addresses, and nothing but memory addresses and may be used or thought of interchangeably with memory addresses". The distinction is important)

Billposter answered 8/8, 2008 at 6:18 Comment(2)
After all, a null pointer doesn't point to zero-address in the memory, even though it's C "value" is zero. It's an entirely separate concept, and if you deal with it wrong, you might end up addressing (and dereferencing) something you didn't expect to. In some cases, that might even be zero-address in the memory (especially now that address space is usually flat), but in others, it might be omitted as undefined behaviour by an optimizing compiler, or access some other part of memory that's associated with "zero" for the given pointer type. Hilarity ensues.Woden
Not necessarily. You need to be able to model the computer in your head for pointers to make sense (and to debug others programs as well). Not everybody can do this.Ogilvie
K
8

The problem with pointers is not the concept. It's the execution and language involved. Additional confusion results when teachers assume that it's the CONCEPT of pointers that's difficult, and not the jargon, or the convoluted mess C and C++ makes of the concept. So vast amounts of effort are poored into explaining the concept (like in the accepted answer for this question) and it's pretty much just wasted on someone like me, because I already understand all of that. It's just explaining the wrong part of the problem.

To give you an idea of where I'm coming from, I'm someone who understands pointers perfectly well, and I can use them competently in assembler language. Because in assembler language they are not referred to as pointers. They are referred to as addresses. When it comes to programming and using pointers in C, I make a lot of mistakes and get really confused. I still have not sorted this out. Let me give you an example.

When an api says:

int doIt(char *buffer )
//*buffer is a pointer to the buffer

what does it want?

it could want:

a number representing an address to a buffer

(To give it that, do I say doIt(mybuffer), or doIt(*myBuffer)?)

a number representing the address to an address to a buffer

(is that doIt(&mybuffer) or doIt(mybuffer) or doIt(*mybuffer)?)

a number representing the address to the address to the address to the buffer

(maybe that's doIt(&mybuffer). or is it doIt(&&mybuffer) ? or even doIt(&&&mybuffer))

and so on, and the language involved doesn't make it as clear because it involves the words "pointer" and "reference" that don't hold as much meaning and clarity to me as "x holds the address to y" and "this function requires an address to y". The answer additionally depends on just what the heck "mybuffer" is to begin with, and what doIt intends to do with it. The language doesn't support the levels of nesting that are encountered in practice. Like when I have to hand a "pointer" in to a function that creates a new buffer, and it modifies the pointer to point at the new location of the buffer. Does it really want the pointer, or a pointer to the pointer, so it knows where to go to modify the contents of the pointer. Most of the time I just have to guess what is meant by "pointer" and most of the time I'm wrong, regardless of how much experience I get at guessing.

"Pointer" is just too overloaded. Is a pointer an address to a value? or is it a variable that holds an address to a value. When a function wants a pointer, does it want the address that the pointer variable holds, or does it want the address to the pointer variable? I'm confused.

Kurtiskurtosis answered 8/8, 2008 at 6:18 Comment(6)
I've seen it explained like this: if you see a pointer declaration like double *(*(*fn)(int))(char), then the result of evaluating *(*(*fn)(42))('x') will be a double. You can strip off layers of evaluation to understand what the intermediate types must be.Bulwark
@BerndJendrissek Not sure I follow. What's the result of evaluating (*(*fn)(42))('x') then?Kurtiskurtosis
you get a thing (let's call it x) where, if you evaluate *x, you get a double.Bulwark
@BerndJendrissek Is this supposed to explain something about pointers? I don't get it. What's your point? I've stripped off a layer, and gained no new information about any intermediate types. What does it explain about what a particular function is going to accept? What does it have to do with anything?Kurtiskurtosis
Maybe the message in this explanation (and it isn't mine, I wish I could find where I first saw it) is to think of it less in terms of what fn is and more in terms of what you can do with fnBulwark
clear as mud. What does fn, or any of it have to do with my original answer? Please believe me when I say I don't even slightly understand what you are getting at, or what this relates to, other than it has something to do with pointers. Maybe you are trying to clarify or explain something, I just can't figure out what. About as far as I can get is that a type annotation like "double" signifies the type of its argument. But that's types. When questioned about what the type annotation has to do with pointers you piked. You are going to have to go back to the beginning. Assume I know nothing.Kurtiskurtosis
B
5

I could work with pointers when I only knew C++. I kind of knew what to do in some cases and what not to do from trial/error. But the thing that gave me complete understanding is assembly language. If you do some serious instruction level debugging with an assembly language program you've written, you should be able to understand a lot of things.

Biogen answered 8/8, 2008 at 6:18 Comment(0)
T
5

The reason it's so hard to understand is not because it's a difficult concept but because the syntax is inconsistent.

int *mypointer;

You are first learned that the leftmost part of a variable creation defines the type of the variable. Pointer declaration does not work like this in C and C++. Instead they say that the variable is pointing on the type to the left. In this case: *mypointer is pointing on an int.

I didn't fully grasp pointers until i tried using them in C# (with unsafe), they work in exact same way but with logical and consistent syntax. The pointer is a type itself. Here mypointer is a pointer to an int.

int* mypointer;

Don't even get me started on function pointers...

Tuppeny answered 8/8, 2008 at 6:18 Comment(14)
Actually, both of your fragments are valid C. It is a matter of a lot of years of C style that the first one is more common. The second is quite a bit more common in C++, for instance.Poise
The second fragment doesn't really work well with more complex declarations. And the syntax isn't as "inconsistent" once you realize that the right-hand part of a pointer declaration shows you what you must do to the pointer in order to get something whose type is the atomic type specifier on the left.Bulwark
int *p; has a simple meaning: *p is an integer. int *p, **pp means: *p and **pp are integers.Thusly
@MilesRout: But that's exactly the problem. *p and **pp are not integers, because you never initialised p or pp or *pp to point to anything. I understand why some people prefer sticking with the grammar on this one, particularly because some edge cases and complex cases require you to do so (though, still, you can trivially work around that in all cases I'm aware of) ... but I don't think those cases are more important than the fact that teaching right-alignment is misleading to newbies. Not to mention kind of ugly! :)Siddur
@LightnessRacesinOrbit Teaching right-alignment is far from misleading. It is the only correct way of teaching it. NOT teaching it is misleading.Thusly
@MilesRout: I'm sorry you think so. At least now I've discovered people are actually actively and proudly teaching this calamity, rather than it simply being something newbies pick up from poorly written "tuts". So that's something!Siddur
@LightnessRacesinOrbit It's not a calamity, it's how it works logically! It makes sense! int *foo means *foo is an int. int (*foo)(int, int) means that (*foo)(1, 2) is an int.Thusly
@LightnessRacesinOrbit Your "are not integers because you never initialised them" point is stupid, we're talking about it on a type system level.Thusly
@MilesRout: It's not "stupid": this is an incredibly frequent source of confusion for millions of novice programmers and it leads to an incredible number of bugs. p is an int*, period. That makes sense. And I would ask you to find a way to make your point without resorting to derogatory comments.Siddur
@MilesRout #34091642Siddur
@LightnessRacesinOrbit You're reinforcing my point - it was confusing for it to be written int* p and not int *p in that example.Thusly
@MilesRout: Er, no, the OP was confused because he'd originally read const Stock &p and misunderstood it as a consequence. It was only when seeing const Stock& p that the truth dawned on the OP, after some help through the transition. Not sure why you're wilfully misrepresenting events and hoping I won't notice?!Siddur
One issue with left aligning the * is when multiple variables are declared on the same line - which is valid C and C++: int* p, q, r; may imply to the unwary that p, q and r are all pointers to integer values, when actually of course only the first is - the other two being integer values themselves - which is visually more obvious with int *p, q, r;. Actually I'd tend to int * p, q, r; or more likely move the pointer declaration to a separate line, but perhaps that is me being middle of the road...Clamorous
Also, technically pointers are an unsigned integer type but it is NOT a good idea to delve too deeply into the binary representation unless you are coding a compiler where you cannot afford to make assumptions about their content - perhaps after reading this Q&A the reader might see why pointers (addresses) should be treated as different from other integer data types even though there are some analogous operations that can be done on both! They are oranges and apples.Clamorous
P
5

I think that what makes pointers tricky to learn is that until pointers you're comfortable with the idea that "at this memory location is a set of bits that represent an int, a double, a character, whatever".

When you first see a pointer, you don't really get what's at that memory location. "What do you mean, it holds an address?"

I don't agree with the notion that "you either get them or you don't".

They become easier to understand when you start finding real uses for them (like not passing large structures into functions).

Procambium answered 8/8, 2008 at 6:18 Comment(0)
P
4

I like the house address analogy, but I've always thought of the address being to the mailbox itself. This way you can visualize the concept of dereferencing the pointer (opening the mailbox).

For instance following a linked list: 1) start with your paper with the address 2) Go to the address on the paper 3) Open the mailbox to find a new piece of paper with the next address on it

In a linear linked list, the last mailbox has nothing in it (end of the list). In a circular linked list, the last mailbox has the address of the first mailbox in it.

Note that step 3 is where the dereference occurs and where you'll crash or go wrong when the address is invalid. Assuming you could walk up to the mailbox of an invalid address, imagine that there's a black hole or something in there that turns the world inside out :)

Photoplay answered 8/8, 2008 at 6:18 Comment(1)
A nasty complication with the mailbox-number analogy is that while the language invented by Dennis Ritchie defines behavior in terms the addresses of bytes and the values stored in those bytes, the language defined by the C Standard invites "optimizing" implementations to use a behavioral model which is more complicated but defines various aspects of the model in ways that are ambiguous, contradictory, and incomplete.Concavity
E
3

I think that the main reason that people have trouble with it is because it's generally not taught in an interesting and engaging manner. I'd like to see a lecturer get 10 volunteers from the crowd and give them a 1 meter ruler each, get them to stand around in a certain configuration and use the rulers to point at each other. Then show pointer arithmetic by moving people around (and where they point their rulers). It'd be a simple but effective (and above all memorable) way of showing the concepts without getting too bogged down in the mechanics.

Once you get to C and C++ it seems to get harder for some people. I'm not sure if this is because they are finally putting theory that they don't properly grasp into practice or because pointer manipulation is inherently harder in those languages. I can't remember my own transition that well, but I knew pointers in Pascal and then moved to C and got totally lost.

Emaciation answered 8/8, 2008 at 6:18 Comment(0)
T
2

The way I liked to explain it was in terms of arrays and indexes - people might not be familiar with pointers, but they generally know what an index is.

So I say imagine that the RAM is an array (and you have only 10-bytes of RAM):

unsigned char RAM[10] = { 10, 14, 4, 3, 2, 1, 20, 19, 50, 9 };

Then a pointer to a variable is really just the index of (the first byte of) that variable in the RAM.

So if you have a pointer/index unsigned char index = 2, then the value is obviously the third element, or the number 4. A pointer to a pointer is where you take that number and use it as an index itself, like RAM[RAM[index]].

I would draw an array on a list of paper, and just use it to show things like many pointers pointing to the same memory, pointer arithmetic, pointer to pointer, and so on.

Tango answered 8/8, 2008 at 6:18 Comment(0)
C
2

The confusion comes from the multiple abstraction layers mixed together in the "pointer" concept. Programmers don't get confused by ordinary references in Java/Python, but pointers are different in that they expose characteristics of the underlying memory-architecture.

It is a good principle to cleanly separate layers of abstraction, and pointers do not do that.

Crowfoot answered 8/8, 2008 at 6:18 Comment(3)
Interesting thing is, that C pointers actually don't expose any charasteristic of the underlying memory architecture. The only differences between Java references and C pointers are that you can have complex types involving pointers (eg. int*** or char* ()(void*)), there is pointer arithmetic for arrays and pointers to struct members, the presence of the void*, and array/pointer duality. Other than that, they work just the same.Armillas
Good point. It's the pointer arithmetic and the possibility of buffer overflows -- breaking out of the abstraction by breaking out of the currently relevant memory area -- that does it.Crowfoot
@jpalecek: It's pretty easy to understand how pointers work on implementations that document their behavior in terms of the underlying architecture. Saying foo[i] means going to a certain spot, moving forward a certain distance, and seeing what's there. What complicates things is the much more complicated extra abstraction layer which was added by the Standard purely for the benefit of the compiler, but models things in a way that is a bad fit for programmer needs and compiler needs alike.Concavity
C
2

I think it might actually be a syntax issue. The C/C++ syntax for pointers seems inconsistent and more complex than it needs to be.

Ironically, the thing that actually helped me to understand pointers was encountering the concept of an iterator in the c++ Standard Template Library. It's ironic because I can only assume that iterators were conceived as a generalization of the pointer.

Sometimes you just can't see the forest until you learn to ignore the trees.

Composition answered 8/8, 2008 at 6:18 Comment(4)
The problem is mostly in the C declaration syntax. But pointer use would sure be easier if (*p) would have been (p->), and thus we'd have p->->x instead of the ambiguous *p->xNidify
@Nidify Oh my god you're joking, right? There are no inconsistencies there. a->b simply means (*a).b.Thusly
@Miles: Indeed, and by that logic * p->x means * ((*a).b) whereas *p -> x means (*(*p)) -> x. Mixing prefix and postfix operators causes ambiguous parsing.Nidify
@Nidify no, because whitespace is irrelevant. That's like saying that 1+2 * 3 should be 9.Thusly
S
2

I don't think that pointers themselves are confusing. Most people can understand the concept. Now how many pointers can you think about or how many levels of indirection are you comfortable with. It doesn't take too many to put people over the edge. The fact that they can be changed accidently by bugs in your program can also make them very difficult to debug when things go wrong in your code.

Steppe answered 8/8, 2008 at 6:18 Comment(0)
B
1

Some answers above have asserted that "pointers aren't really hard", but haven't gone on to address directly where "pointer are hard!" comes from. Some years back I tutored first year CS students (for only one year, since I clearly sucked at it) and it was clear to me that the idea of pointer is not hard. What's hard is understanding why and when you would want a pointer.

I don't think you can divorce that question - why and when to use a pointer - from explaining broader software engineering issues. Why every variable should not be a global variable, and why one should factor out similar code into functions (that, get this, use pointers to specialize their behaviour to their call site).

Bulwark answered 8/8, 2008 at 6:18 Comment(0)
E
1

Not a bad way to grasp it, via iterators.. but keep looking you'll see Alexandrescu start complaining about them.

Many ex-C++ devs (that never understood that iterators are a modern pointer before dumping the language) jump to C# and still believe they have decent iterators.

Hmm, the problem is that all that iterators are is in complete odds at what the runtime platforms (Java/CLR) are trying to achieve: new, simple, everyone-is-a-dev usage. Which can be good, but they said it once in the purple book and they said it even before and before C:

Indirection.

A very powerful concept but never so if you do it all the way.. Iterators are useful as they help with abstraction of algorithms, another example. And compile-time is the place for an algorithm, very simple. You know code + data, or in that other language C#:

IEnumerable + LINQ + Massive Framework = 300MB runtime penalty indirection of lousy, dragging apps via heaps of instances of reference types..

"Le Pointer is cheap."

Eluvium answered 8/8, 2008 at 6:18 Comment(3)
What does this have to do with anything?Romy
... what are you trying to say, apart from "static linking is the best thing ever" and "I don't understand how anything different than what I've learned previously works"?Woden
Luaan, you couldn't possibly know what one can learn by disassembling the JIT in 2000 could you? That it ends up in a jump table, from a pointer table, as shown in 2000 online in ASM, so not understanding anything different can take another meaning: reading carefully is an essential skill, try it again.Eluvium
P
1

Post office box number.

It's a piece of information that allows you to access something else.

(And if you do arithmetic on post office box numbers, you may have a problem, because the letter goes in the wrong box. And if somebody moves to another state -- with no forwarding address -- then you have a dangling pointer. On the other hand -- if the post office forwards the mail, then you have a pointer to a pointer.)

Phantasm answered 8/8, 2008 at 6:18 Comment(0)
S
0

Every C/C++ beginner has the same problem and that problem occurs not because "pointers are hard to learn" but "who and how it is explained". Some learners gather it verbally some visually and the best way of explaining it is to use "train" example (suits for verbal and visual example).

Where "locomotive" is a pointer which can not hold anything and "wagon" is what "locomotive" tries pull (or point to). After, you can classify the "wagon" itself, can it hold animals,plants or people (or a mix of them).

Sweetener answered 8/8, 2008 at 6:18 Comment(0)
U
0

Just to confuse things a bit more, sometimes you have to work with handles instead of pointers. Handles are pointers to pointers, so that the back end can move things in memory to defragment the heap. If the pointer changes in mid-routine, the results are unpredictable, so you first have to lock the handle to make sure nothing goes anywhere.

http://arjay.bc.ca/Modula-2/Text/Ch15/Ch15.8.html#15.8.5 talks about it a bit more coherently than me. :-)

Uncloak answered 8/8, 2008 at 6:18 Comment(4)
-1: Handles are not pointers to pointers; they are not pointers in any sense. Don't confuse them.Michael
"They are not pointers in any sense" -- um, I beg to differ.Uncloak
A pointer is a memory location. A handle is any unique identifier. It might be a pointer, but it might just as well be an index in an array, or anything else for that matter. The link you gave is just a special case where the handle is a pointer, but it doesn't have to be. See also parashift.com/c++-faq-lite/references.html#faq-8.8Michael
That link doesn't support your assertion that they aren't pointers in any sense, either -- "For example, the handles might be Fred**, where the pointed-to Fred* pointers..." I don't think the -1 was fair.Uncloak
S
0

I don't see what is so confusing about pointers. They point to a location in memory, that is it stores the memory address. In C/C++ you can specify the type the pointer points to. For example:

int* my_int_pointer;

Says that my_int_pointer contains the address to a location that contains an int.

The problem with pointers is that they point to a location in memory, so it is easy to trail off into some location you should not be in. As proof look at the numerous security holes in C/C++ applications from buffer overflow (incrementing the pointer past the allocated boundary).

Seventieth answered 8/8, 2008 at 6:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.