38

Recently I've been trying to explain pointers in a visual way, as flashcards.

Question 001: This is the drawing of a location in computer memory. Is it true that its address is 0x23452? Why?

enter image description here

Answer: Yes, because 0x23452 describes where the computer can find this location.


Question 002: Is it true that the character b is stored inside the memory location 0x23452? Why?

enter image description here

Answer: No, because the character a is actually stored inside it.


Question 003: Is it true that a pointer is stored inside the memory location 0x23452? Why?

enter image description here

Answer: Yes, because the address of memory location 0x34501 is stored inside it.


Question 004: Is it true that a pointer is stored inside the memory location 0x23452? Why?

enter image description here

Answer: Yes, because the address of another memory location is stored inside it.


Now for the part that has got me worried. A software engineer explained pointers to me like this:

A pointer is a variable whose value is the memory address of another variable.

Based on the four flashcards I've shown you all, I'd define pointers in a slightly different way:

A pointer is a memory location whose value is the memory address of another memory location.

Is it safe to say that a variable is the same thing as a memory location?

If not, then who's right? What's the difference between a variable and a memory location?

  • 37
    There's an implicit assumption here that everyone reading those pictures will know your intent that the hexadecimal number under the box is a memory address, and that the a, 0x23453. nil etc. stuff inside them are the values. That might seem obvious to you, but I wouldn't be comfortable giving decisive answers to those questions without seeing how those fields are defined. There's really no way of knowing if a in the second image is a character, a string (if they're any different), or the name of a variable. If it is a string, then is nil also a string? Or a "null" value? – ilkkachu Aug 29 at 11:54
  • 39
    Question 1 is a bad question. That is something that you need to tell the readers before they can answer the other questions. Instead of a question, it should be information given to the reader: "In the following questions, the boxes are memory locations and the hex numbers underneath are their addresses". – 17 of 26 Aug 29 at 12:15
  • 15
    Question 3 is impossible to answer given the context. There is no way to tell at the byte level how the value stored in memory is being interpreted/used at the application level. – 17 of 26 Aug 29 at 12:19
  • 6
    Worth noting: everything you're writing here is true for C or C++ but false for basically any language that doesn't have explicit pointer referencing/dereferencing. The whole metaphor of variables being slots that values get put into breaks down for a language (like Python, or Java, or C#, or Ruby, or JavaScript, or many others) where assignment just makes a variable point to an object without copying it, and mutations to the object are visible through all variables pointing to it. Python's documentation uses the alternative metaphor of variables as nametags hanging on objects for this reason. – Mark Amery Aug 29 at 12:24
  • 19
    BTW, and forgive me if you already understand this, but it looks like this may be a point of confusion - this "0x23452" notation is just a way to denote a number in hexadecimal format, and it's just done for convenience. But it's just a number - in no way does the 0x prefix denote that it's a pointer, what's stored in memory is literally just a meaningless number (you could label memory locations with plain decimal integers). The meaning (i.e., how the number should be interpreted) comes from the language - the type of the variable & the way it is used. – Filip Milovanović Aug 29 at 20:26

10 Answers 10

69

A variable is a logical construct that goes to the intent of an algorithm, whereas a memory location is a physical construct that describes the operation of a computer.  Generally speaking, in order to execute a program there is (compiler generated) mapping between the logical notion of a variable and the storage of the computer.

(Even in assembly language we have a notion of (logical) variables going to algorithm and intent, and (physical) memory locations, though they are more conflated in assembly.)

A variable is a high(er) level concept.  A variable represents either an unknown (as in mathematics, or programming assignment) or a place-holder that can be substituted with a value (as in programming: parameters).

A memory location is a low(er) level concept.  A memory location can be used to store a value, sometimes, to store the value of a variable.  However, a CPU register is another way to store the value of some variable(s).  CPU registers are also low(er) level storage locations, but they are not memory locations as they do not have addresses, just names.

In some sense, a variable is a mechanism of abstraction for expressing intent of the program, whereas a memory location is a physical entity of the processing environment that provides storage & retrieval.

Question 003: Is it true that a pointer is stored inside the memory location 0x23452? Why?

We cannot say fore sure.  Just because there is a value there that would work as an address, doesn't mean it is that address, it could be the integer (decimal) ‭144466‬, instead.  We cannot make assumptions on the interpretation of values merely based on how they appear numerically.

Question 004: Is it true that a pointer is stored inside the memory location 0x23452? Why?

This is indeed an odd question.  They expect some assumptions based on the boxes, however, let's note that the addresses increase by 1 for each box.  In any modern computer, that would mean that each box can hold a byte — byte addressability has been the norm for decades now.  However a byte is only 8-bits and can range from 0 to 255 (for unsigned values); yet they show a much larger value stored within one of these addresses, so very suspicious.  (This could work if this were a word addressed machine, but it doesn't say that, and, few machines today are, though some educational machines are so.)

Based on the four flashcards I've shown you all, I'd define pointers in a slightly different way:

A pointer is a memory location whose value is the memory address of another memory location.

While there are situations where this thinking is correct, you are mixing metaphors here.  The notion of a variable goes to the algorithm and its intent — there is no need to assume all variables have memory locations.  Some variables (especially arrays) have memory locations because memory locations support addressing (whereas CPU registers can only be named not indexed).

For execution, there is a logical mapping between variables & statements and processor memory locations & processor instruction sequences.  A variable whose value never changes (e.g. a constant) does not even necessarily require a memory location, since the value can be reproduced at will (e.g. as needed for code sequences generated by the compiler).

  • 4
    And even 8-bit bytes are still not universal. – Deduplicator Aug 29 at 12:37
  • 14
    @JimmyJames Consider the case of a for loop index when the compiler decides to completely unroll the loop. Nowhere in the produced output code (be it assembly or machine code or byte code) is there a memory location in which the loop counter gets stored. But it is still a variable. – dmckee Aug 29 at 15:04
  • 4
    @JimmyJames, In the case of the unrolled-loop pointer, then yes, if your code actually uses the value of the counter, then it has to be loaded somewhere, but (a) that place could be a register, and (b) there's no reason in principle why it would have to be the same location on every iteration of the unrolled loop. – Solomon Slow Aug 29 at 19:08
  • 3
    If the loop is doing something like copying fixed length array source into equal length array dest a loop coded as for (int i=0; i<8; ++i) dest[i] = source[i]; might well compile down to a something equivalent to repetition of dest++ = source++; the apposite number of times. With the loop counter itself is nowhere in evidence (not even in register), and only the number of repetitions tells you about the loop condition. – dmckee Aug 29 at 19:18
  • 2
    The distinction is confused somewhat by languages like C whose semantics are closely based on an abstraction of a machine whose memory consists of numbered locations. – Michael Kay Aug 30 at 9:12
20

Is it safe to say that a variable is the same thing as a memory location?

No. Variable and memory location are two abstractions at two different abstraction levels. Variable and pointers are higher level concept at the code/language level, memory location is a lower level concept at the machine level. Once a code had been compiled into an executable, there's no longer any variables. Trying to talk about memory location and variables in this manner is a categorical error.

A variable may be implemented using the memory, but not always as a compiler can optimise a calculation and do all calculations relating to a variable entirely in registers, or it can put a single variable to multiple memory locations, or it can use a single memory location for multiple variables.

A pointer is a memory location whose value is the memory address of another memory location.

This series of flashcard is so confused, they're not just not right, but they're not even wrong.

  • 1
    Once a code had been compiled into an executable, there's no longer any variables. That is something I arguably disagree with. It's correct that your variable as you know it (i.e. by that name) no longer exists, but your phrasing seems to suggest that the compiled executable only uses memory addresses. That's not correct. Your compiled-but-not-executing executable has no idea which memory addresses it will use when it executes. The concept of a variable (i.e. a reusable reference to whichever memory address that will be assigned at runtime) still exists inside of the compiled executable. – Flater Aug 29 at 9:49
  • 2
    Or the compiler could optimize the variable completely away, in various ways. Pre-computing something, pruning unnecessary variables. If the variable is a constant, then the compiler could end up using CPU instructions which use constants, and I'd argue then that no longer counts as the variable being anywhere. – kutschkem Aug 29 at 13:47
16

Variables are language constructs. They have a name, reside within a scope, may be referenced by other parts of the code, etc. They are a logical entity. The compiler is free to implement this language construct in any way it pleases, as long as the observable behavior is that prescribed by the language standard. As such, the variable does not even need to be stored anywhere if the compiler can prove that that's not needed.

Memory locations are a hardware concept. They signify a place in virtual/physical memory. Every memory location has exactly one physical address and any amount of virtual addresses that may be used to manipulate it. But there's always exactly one byte stored at each memory location.

Pointers are a special kind of values. Saying something is a pointer is akin to saying something is of type double. It signifies how many bits are used for the value, and how those bits are interpreted, but it does not mean that this value is stored in a variable, nor does it mean that this value is stored in memory.


To give an example in C: When I have an 2D array int foo[6][7]; and I access an element of it with foo[1][2], then foo is a variable that holds an array. When foo is used in this context, it is turned into a pointer to the first element of the array. This pointer is not stored in any variable, nor is it stored in memory, it's value is only generated within a register of the CPU, used, and then forgotten. Likewise, the expression foo[1] is turned into another pointer in this context, which, again, is not in a variable, is not stored in memory, but computed in the CPU, used, and forgotten. The three concepts variable, memory location and pointer are really three different concepts.


Btw, I really meant "there's always exactly one byte stored at each memory location". This was not the case in the stone age of computing some fifty years ago, but it is true for virtually all hardware that's in use today. Whenever you store a value in memory that's larger than one byte, you are actually using a number of consecutive memory locations. I.e. (assuming big endian byte order) the number 0x01234567 is stored in memory as

+------+------+------+------+
| 0x01 | 0x23 | 0x45 | 0x67 |
+------+------+------+------+
    ^      ^      ^      ^
    |      |      |      |
 0x4242 0x4243 0x4244 0x4245

(Little endian machines like the X86 architecture store the bytes in reverse order.) This is true for pointers as well: A pointer on a 64 bit machine is stored in eight consecutive bytes, each with its own memory address. You cannot look at a memory cell and say: "Oh, this is a pointer!" You always only see bytes when you look at memory.

  • How does the computer know when a group of consecutive memory locations starts and ends? – progner Aug 29 at 16:20
  • 6
    @progner It doesn't. It interprets the bytes in memory according to the instructions it gets. Those instructions are also stored in nothing but a sequence of bytes themselves. To the CPU the only difference between a byte that holds an instruction, a byte that holds a character, and a byte that holds some floating point bits, is how it was instructed to use this byte. If the byte is fetched because the program counter points to it, it's used as an instruction. If it's fetched because an instruction says to load it into a float register, it's used as floating point data. – cmaster Aug 29 at 16:47
  • 7
    @progner That was actually the key innovation of the von-Neuman architecture: To store both instructions and data in the same memory, allowing instructions to change data that is later executed as more instructions. This allowed self modifying code, but it also allows a system's kernel to load some program into memory, and then tell the CPU to execute that program. Before von-Neuman, computers like the Zuse machines would get their instructions via a channel that was fully independent from the data they operated on. – cmaster Aug 29 at 16:53
5

Let me focus on your actual question - "who's right?" when comparing these two statements:

  • A pointer is a variable whose value is the memory address of another variable
  • A pointer is a memory location whose value is the memory address of another memory location.

The answer to this is none. The first one talks of a "memory address of another variable", but variables do not necessarily have memory adresses, as the other answers already explained. The second one says "a pointer is a memory location", but a pointer is literally just a number, which may be stored in a variable, but as before, a variable does not necessarily have a memory address.

Some examples for more precise statements:

  • "A pointer is a number representing the memory address of a memory location", or

  • "A pointer variable is a variable whose value is the memory address of a memory location."

  • "A memory adress can hold a pointer representing the memory address of a memory location."

Note sometimes the term "pointer" is used as a shortcut for "pointer variable", which is ok as long as it does not lead to confusion.

  • You could change "another" to "a" because a pointer can point to itself. – Pieter B Aug 29 at 8:52
  • @PieterB: nitty, nitty ;-) not sure if this really makes it clearer, since I wanted only to change the original wording to the degree really required to make them sensible. But alas, I made the edit. – Doc Brown Aug 29 at 9:08
  • To be fair, if you get that nitpicky "but a pointer is literally just a number" isn't correct either, actually an pointer is an identifier refferencing a number ;) Or at least we had to know the language specifics to get into these details. – Zaibis Aug 29 at 11:41
  • 2
    A pointer is a value (number is already too specific to some implementations) potentially referring to some object. Potentially as there are also null pointers, wild pointers, and dangling pointers, though some (or even all!) of those may be ruled out by the language used. – Deduplicator Aug 29 at 12:41
  • 2
    @Deduplicator: you are right, but I think the mental model of a pointer as a number is good enough for the purpose of this question. So let's keep things simple. – Doc Brown Aug 29 at 15:02
5

I certainly wouldn't say that a pointer is a memory location that contains an address. For one, I'm not aware of an architecture where 0x23453 could fit in a single byte. :) Even if you handwave away the byte/word distinction, you still have the problem that every memory location contains an address. Addresses are just numbers, and the contents of memory are just numbers.

I think the trick here is that "pointer" describes human intent, not any particular feature of the architecture. It's similar to how a "character" or "string" isn't a concrete thing you can see in memory — those are all just numbers too, but they function as strings because that's how they're treated. "Pointer" merely means a value intended to be used as an address.

Honestly, if your goal is to teach a particular language (Objective C?), I'm not sure drawing out the classic memory tape is even that useful. You're already telling white lies by showing typed values and values too big for a byte. Teach semantics, not mechanics — the key insight about pointers is that they provide indirection, which is a massively useful tool to understand.

I think a good comparison might be to a URL, which tells you where to find some data, but isn't the data itself. Hear me out:

  • You rarely care what the URL actually is; the vast majority of them are squirrelled away in links with names. Plenty of people use the internet without knowing exactly how a URL results in a page; some people are oblivious to URLs entirely.

  • Not every string is a URL, or intended to be used as a URL.

  • If you try to visit a bogus URL, or a page that used to exist but has since been deleted, you get an error.

  • A URL might point to an image, some text, some music, or any number of other individual items — or it might point to a page with a variety of things contained within. It's very common to have a whole bunch of pages with similar layouts but different data.

  • If you make a web page, and you want to refer to data on some other web page, you don't need to copy and paste it all in; you can just make a link to it.

  • Any number of other pages can link to the same URL.

  • If you have a collection of similar pages, you might make an index page that lists links to all of them, or you might just have a "next" link at the bottom of page 1 that takes you to page 2, and so on. The advantages and disadvantages of both approaches are immediately obvious, especially if you consider what the webmaster would need to do to add or remove pages in various places.

This analogy makes it very clear what pointers are for, which is critical to understanding them — otherwise they just seem arbitrary, complicated, and pointless. Understanding how something works is much easier if you already understand what it does and why it's useful. If you've already internalized that a pointer is some black box that tells you where something else is, and then you learn about the intricacies of the memory model, then representing pointers as addresses is fairly obvious. Plus, teaching semantics will put your students in a much better place for understanding and inventing other forms of indirection — which is good when most major languages don't have pointers at all!

  • every memory location contains an address -- Every memory location has an address. It's not contained anywhere, except maybe in a pointer variable. – Robert Harvey Aug 31 at 16:54
  • @RobertHarvey every memory location (word, at least) contains a number, which could be trivially interpreted as an address. the point was that nothing in the hardware actually distinguishes addresses from non-addresses – Eevee Sep 1 at 13:01
2

I know you've already accepted an answer, and this question has five answers already, but there's a point they don't mention, one that I think tripped you up. CS textbooks often try to be agnostic about the choice of programming language, which leads to the implicit assumption that the terminology used to describe things is universal. It isn't.

In C, the unary ampersand operator is called the "address-of" operator. C programmers would not hesitate to say that the expression &x evaluates to the address of the variable x. Of course they mean "the memory address in which the value of the variable x is stored" but nobody is that pedantic in casual conversation. In C the word "pointer" usually refers to the data type of a variable intended have a memory address as its value. Or equivalently the data type of the value. But some people would use "pointer" as the value itself.

In Java, all variables of object or array type behave a lot like C pointers (except for pointer arithmetic), but Java programmers call them references, not pointers.

C++ considers references and pointers to be different concepts. They're related, but not quite the same thing, so C++ programmers have to make the distinction in conversation. The ampersand is read as "address-of" in some contexts, and "reference-to" in others.

A pointer is a variable whose value is the memory address of another variable.

That's how a C programmer might describe it, using "a pointer" in the same sense as "an int." (As in,"a pointer holds a memory address while an int holds an integer within a certain range.")

A pointer is a memory location whose value is the memory address of another memory location.

That's an odd way to say it, because it requires a very loose and informal definition of "is."

Is it safe to say that a variable is the same thing as a memory location?

It would be clearer to say a memory address is the location in memory where the value of a variable is stored. (Granted, not all variables are stored in memory, due to compiler optimizations, but any variable whose address is taken with &x will be.)

  • As we are being pedantic: The address at which something is stored. Aside from an address not being able to store anything, often things are stored in multiple adjacent locations only one of which (generally selected by a somewhat consistent rule) is addressed (and only using one of potentially many addresses). – Deduplicator Aug 29 at 23:28
  • @Deduplicator I for one am not trying to be pedantic. – gatkin Aug 29 at 23:48
  • The C standard even distinguishes, formally, between variables that must strictly follow the steps of the abstract machine at every “sequence point”—for the sake of thread safety and certain low-level operations on memory-mapped hardware—and those that don’t, which are free to be moved into a register or optimized away completely. – Davislor Aug 30 at 2:12
  • @Davislor: The C Standard uses the term "object" in places where other language specifications use "variable", as well as to describe other things that aren't variables. Some discussions may use the language-agnostic term "variable", but for whatever reason the Standard lacks a term to distinguish between named disjoint allocations (variables) from other kinds of objects like nested allocations (struct/union members) or the unnamed objects yielded by dereferencing pointers. Informally, "variable" is a great term, but the Standard doesn't use it. – supercat Aug 30 at 15:50
  • @supercat That is not correct. The C11 standard uses the term “variable” more than a hundred times, of which several dozen are nouns, e.g., “Concurrent access to the variable being initialized, even via an atomic operation,constitutes a data race.” – Davislor Aug 31 at 3:36
1

The statement A pointer is a variable whose value is the memory address of another variable is oversimplified. But by the time a reader understands what exactly a memory location is, and how it differs from a variable, they will already understand what exactly a pointer is and therefore no longer need to rely on this inaccurate explanation.

The statement A pointer is a memory location whose value is the memory address of another memory location is wrong. The value of a pointer does not need to be stored in a memory location, and it's debatable if a pointer needs to point to a memory location, depending on the intended definition of "memory".

What's the difference between a variable and a memory location

A memory location is one of multiple possible places where data can be stored. That data can be a variable, or part of a variable. Variables are a way of labeling data.

0

This answer focuses on C and C++; that seems appropriate since your question is concerned with pointers which are a more integral part of C/C++ than of other languages. Most of this post will apply to most compiled languages without an elaborate run time (like Pascal or Ada, but not like Java or C#).

The good answers already given emphasize that a variable is a language construct on a more abstract level than physical memory. I'd like to emphasize though that this abstraction has a certain rationale and system to it:

The abstraction mainly consists in using a name instead of a literal address.

The principle idea is that a variable is a named handle for a typed object; objects in C/C++ are usually in memory. The languages then add some niceties concerning lifetime management and data marshaling for type conversions. The concept of variables is more abstract than physical addresses because we don't actually care about the numerical value of addresses or the exact location of functions in memory. We simply name them and later address them by name, and the compiler, linker and runtime system take care of the gritty details.

And do not pretend that C/C++ are memory agnostic: There is, after all, the universally applicable address operator. Yes, true, you cannot take the address of a C variable in the register storage class; but when have you last used one? It is a special exception to the general concept, not a wholesale dismissal of the argument. The general rule is, to the contrary, that taking an address of a variable actually forces the compiler to indeed create an object in memory, even if it wouldn't do so otherwise (e.g. with constants). The "named handle" concept is also a good paradigm for C++ references: A reference is just another name for the same object.

When I wrote inline assembler for 68k it was nice to see how you could use variable names as offsets to address registers (and you could use the names of variables declared register instead of the bare metal register names!). To the compiler, a variable is a constant address offset. To reiterate: Variables are named handles, usually for objects in memory.

  • Pointers are a very basic part of C#, Java, JS, and other languages too. Calling them differently doesn't change that, though it is good PR. – Deduplicator Aug 30 at 11:25
  • @Deduplicator :-) Good ol' Tony... – Peter - Reinstate Monica Aug 30 at 11:39
0

It sounds as though the question is aimed at a popular language formed by augmenting the C Standard with the additional guarantee "In cases where some parts of the Standard or an implementation's documentation describe the behavior of some action, and some other part categorizes it as undefined, the former part dominates.", as well as a definition of "variable" consistent with other languages' use of the term.

In that language, each memory location can be viewed as a numbered mailbox that always holds some number (typically eight) of bits, each of which can independently be zero or one. Memory locations are typically organized in rows of two, four, or eight. and some operations process on multiple consecutive memory locations at once. Depending upon the machine, some operations that that operate on groups of two, four, or eight memory locations may be limited to operating on locations within a single row. Further, while some machines may have a single room of consecutively-numbered mailboxes, others may have multiple disjoint groups of numbered mailboxes.

A variable identifies a range of memory locations that are associated exclusively with it, and a type as which those memory locations should be interpreted. Reading a variable will cause the bits within its associated storage locations to be interpreted in a manner appropriate to the variable's type, and writing a variable will cause the associated bits to be set in a manner appropriate to its type and value.

An address encapsulates whatever information is necessary to identify a mailbox. This may be stored as a simple number, or as some kind of group designator along with the number of a mailbox within that group.

Applying the & operator to a variable will yield a pointer that encapsulates the address and type thereof. Applying the unary * or [] operator to a pointer will cause the bits of mailboxes starting at encapsulated address to be interpreted or set in a manner appropriate to the encapsulated type.

  • It sounds as though you're overthinking the question. – Robert Harvey Aug 31 at 16:50
0

I'm coming late to this party but I can't resist putting my 2 cents in.

At these times, what is the difference between the values stored in these memory locations?

Time 1

enter image description here

Time 2

enter image description here

Correct answer: nothing. They are all identical values being presented with different interpretations of their meaning.

How do I know that? Because I'm the one who made this up. You don't really know that yet.

You are running into something I call the out of band problem. How to correctly interpret the meaning of these values is not stored here. That knowledge is stored elsewhere. Yet when you present these values on paper you put in that interpretation. That means you've added information that simply doesn't exist in these memory locations.

For example, the values here are identical, but you only know that to be true if you are correct when you assume an ASCII / UTF-8 character encoding is how I got the first one, rather than say EBCDIC. And you also must assume that the second one is hexadecimal expressions of the numerical values stored at those memory locations, that could all be pointers to other addresses, rather than say references to strings that all happen to start with "0x". :P

Nothing stored in these memory locations tells you any of those assumptions are correct. That information can be stored. But it would be stored elsewhere.

This is the presentation problem. You can't express any number at all without first agreeing on how to present it. You can lean on assumptions, conventions, and context but if you scratch at it deeply, when the presentation isn't explicitly defined, the only truly correct answer is "not enough information".

Not the answer you're looking for? Browse other questions tagged or ask your own question.