What exactly is a C pointer if not a memory address?

37,926

Solution 1

The C standard does not define what a pointer is internally and how it works internally. This is intentional so as not to limit the number of platforms, where C can be implemented as a compiled or interpreted language.

A pointer value can be some kind of ID or handle or a combination of several IDs (say hello to x86 segments and offsets) and not necessarily a real memory address. This ID could be anything, even a fixed-size text string. Non-address representations may be especially useful for a C interpreter.

Solution 2

I'm not sure about your source, but the type of language you're describing comes from the C standard:

6.5.3.2 Address and indirection operators
[...]
3. The unary & operator yields the address of its operand. [...]

So... yeah, pointers point to memory addresses. At least that's how the C standard suggests it to mean.

To say it a bit more clearly, a pointer is a variable holding the value of some address. The address of an object (which may be stored in a pointer) is returned with the unary & operator.

I can store the address "42 Wallaby Way, Sydney" in a variable (and that variable would be a "pointer" of sorts, but since that's not a memory address it's not something we'd properly call a "pointer"). Your computer has addresses for its buckets of memory. Pointers store the value of an address (i.e. a pointer stores the value "42 Wallaby Way, Sydney", which is an address).

Edit: I want to expand on Alexey Frunze's comment.

What exactly is a pointer? Let's look at the C standard:

6.2.5 Types
[...]
20. [...]
A pointer type may be derived from a function type or an object type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation’’. A pointer type is a complete object type.

Essentially, pointers store a value that provides a reference to some object or function. Kind of. Pointers are intended to store a value that provides a reference to some object or function, but that's not always the case:

6.3.2.3 Pointers
[...]
5. An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

The above quote says that we can turn an integer into a pointer. If we do that (that is, if we stuff an integer value into a pointer instead of a specific reference to an object or function), then the pointer "might not point to an entity of reference type" (i.e. it may not provide a reference to an object or function). It might provide us with something else. And this is one place where you might stick some kind of handle or ID in a pointer (i.e. the pointer isn't pointing to an object; it's storing a value that represents something, but that value may not be an address).

So yes, as Alexey Frunze says, it's possible a pointer isn't storing an address to an object or function. It's possible a pointer is instead storing some kind of "handle" or ID, and you can do this by assigning some arbitrary integer value to a pointer. What this handle or ID represents depends on the system/environment/context. So long as your system/implementation can make sense of the value, you're in good shape (but that depends on the specific value and the specific system/implemenation).

Normally, a pointer stores an address to an object or function. If it isn't storing an actual address (to an object or function), the result is implementation defined (meaning that exactly what happens and what the pointer now represents depends on your system and implementation, so it might be a handle or ID on a particular system, but using the same code/value on another system might crash your program).

That ended up being longer than I thought it would be...

Solution 3

Pointer vs Variable

In this picture,

pointer_p is a pointer which is located at 0x12345, and is pointing to a variable variable_v at 0x34567.

Solution 4

To think of a pointer as an address is an approximation. Like all approximations, it's good enough to be useful sometimes, but it's also not exact which means that relying on it causes trouble.

A pointer is like an address in that it indicates where to find an object. One immediate limitation of this analogy is that not all pointers actually contain an address. NULL is a pointer which is not an address. The content of a pointer variable can in fact be of one of three kinds:

  • the address of an object, which can be dereferenced (if p contains the address of x then the expression *p has the same value as x);
  • a null pointer, of which NULL is an example;
  • invalid content, which doesn't point to an object (if p doesn't hold a valid value, then *p could do anything (“undefined behavior”), with crashing the program a fairly common possibility).

Furthermore, it would be more accurate to say that a pointer (if valid and non-null) contains an address: a pointer indicates where to find an object, but there is more information tied to it.

In particular, a pointer has a type. On most platforms, the type of the pointer has no influence at runtime, but it has an influence that goes beyond the type at compile time. If p is a pointer to int (int *p;), then p + 1 points to an integer which is sizeof(int) bytes after p (assuming p + 1 is still a valid pointer). If q is a pointer to char that points to the same address as p (char *q = p;), then q + 1 is not the same address as p + 1. If you think of pointer as addresses, it is not very intuitive that the “next address” is different for different pointers to the same location.

It is possible in some environments to have multiple pointer values with different representations (different bit patterns in memory) that point to the same location in memory. You can think of these as different pointers holding the same address, or as different addresses for the same location — the metaphor isn't clear in this case. The == operator always tells you whether the two operands are pointing to the same location, so on these environments you can have p == q even though p and q have different bit patterns.

There are even environments where pointers carry other information beyond the address, such as type or permission information. You can easily go through your life as a programmer without encountering these.

There are environments where different kinds of pointers have different representations. You can think of it as different kinds of addresses having different representations. For example, some architectures have byte pointers and word pointers, or object pointers and function pointers.

All in all, thinking of pointers as addresses isn't too bad as long as you keep in mind that

  • it's only valid, non-null pointers that are addresses;
  • you can have multiple addresses for the same location;
  • you can't do arithmetic on addresses, and there's no order on them;
  • the pointer also carries type information.

Going the other way round is far more troublesome. Not everything that looks like an address can be a pointer. Somewhere deep down any pointer is represented as a bit pattern that can be read as an integer, and you can say that this integer is an address. But going the other way, not every integer is a pointer.

There are first some well-known limitations; for example, an integer that designates a location outside your program's address space can't be a valid pointer. A misaligned address doesn't make a valid pointer for a data type that requires alignment; for example, on a platform where int requires 4-byte alignment, 0x7654321 cannot be a valid int* value.

However, it goes well beyond that, because when you make a pointer into an integer, you're in for a world of trouble. A big part of this trouble is that optimizing compilers are far better at microoptimization than most programmers expect, so that their mental model of how a program works is deeply wrong. Just because you have pointers with the same address doesn't mean that they are equivalent. For example, consider the following snippet:

unsigned int x = 0;
unsigned short *p = (unsigned short*)&x;
p[0] = 1;
printf("%u = %u\n", x, *p);

You might expect that on a run-of-the-mill machine where sizeof(int)==4 and sizeof(short)==2, this either prints 1 = 1? (little-endian) or 65536 = 1? (big-endian). But on my 64-bit Linux PC with GCC 4.4:

$ c99 -O2 -Wall a.c && ./a.out 
a.c: In function ‘main’:
a.c:6: warning: dereferencing pointer ‘p’ does break strict-aliasing rules
a.c:5: note: initialized from here
0 = 1?

GCC is kind enough to warn us what's going wrong in this simple example — in more complex examples, the compiler might not notice. Since p has a different type from &x, changing what p points to cannot affect what &x points to (outside some well-defined exceptions). Therefore the compiler is at liberty to keep the value of x in a register and not update this register as *p changes. The program dereferences two pointers to the same address and obtains two different values!

The moral of this example is that thinking of a (non-null valid) pointer as an address is fine, as long as you stay within the precise rules of the C language. The flip side of the coin is that the rules of the C language are intricate, and difficult to get an intuitive feeling for unless you know what happens under the hood. And what happens under the hood is that the tie between pointers and addresses is somewhat loose, both to support “exotic” processor architectures and to support optimizing compilers.

So think of pointers being addresses as a first step in your understanding, but don't follow that intuition too far.

Solution 5

A pointer is a variable that HOLDS memory address, not the address itself. However, you can dereference a pointer - and get access to the memory location.

For example:

int q = 10; /*say q is at address 0x10203040*/
int *p = &q; /*means let p contain the address of q, which is 0x10203040*/
*p = 20; /*set whatever is at the address pointed by "p" as 20*/

That's it. It's that simple.

enter image description here

A program to demonstrate what I am saying and its output is here:

http://ideone.com/rcSUsb

The program:

#include <stdio.h>

int main(int argc, char *argv[])
{
  /* POINTER AS AN ADDRESS */
  int q = 10;
  int *p = &q;

  printf("address of q is %p\n", (void *)&q);
  printf("p contains %p\n", (void *)p);

  p = NULL;
  printf("NULL p now contains %p\n", (void *)p);
  return 0;
}
Share:
37,926

Related videos on Youtube

d0rmLife
Author by

d0rmLife

Updated on July 17, 2022

Comments

  • d0rmLife
    d0rmLife almost 2 years

    In a reputable source about C, the following information is given after discussing the & operator:

    ... It's a bit unfortunate that the terminology [address of] remains, because it confuses those who don't know what addresses are about, and misleads those who do: thinking about pointers as if they were addresses usually leads to grief...

    Other materials I have read (from equally reputable sources, I would say) have always unabashedly referred to pointers and the & operator as giving memory addresses. I would love to keep searching for the actuality of the matter, but it is kind of difficult when reputable sources KIND OF disagree.

    Now I am slightly confused--what exactly is a pointer, then, if not a memory address?

    P.S.

    The author later says: ...I will continue to use the term 'address of' though, because to invent a different one [term] would be even worse.

    • WhozCraig
      WhozCraig over 11 years
      A pointer is a variable that holds an address. It also has its own address. This is the fundamental difference between a pointer and an array. An array effectively is an address (and by implication, its address is itself).
    • d0rmLife
      d0rmLife over 11 years
      @WhozCraig Indeed, but the quote is especially keen to note that & doesn't return an actual memory address. So what does it return then?
    • Krishnabhadra
      Krishnabhadra over 11 years
    • Cornstalks
      Cornstalks over 11 years
      What's your "reputable source" for the quote?
    • exebook
      exebook over 11 years
      Pointer has no address, pointer is a value of a "pointer variable" that has an address. But this is neat, so we have pointers as pointer values and pointers as pointer variables. Anything else to confuse newbies even more?
    • Aniket Inge
      Aniket Inge over 11 years
      @exebook pointer has an address because the pointer is also a variable that is holding an address.
    • WhozCraig
      WhozCraig over 11 years
      @exebook Really? pointer has no address? Mkk.int *p = NULL, **pp = &p; So much for that.
    • d0rmLife
      d0rmLife over 11 years
      @Cornstalks Mike Banahan, author of "The C Book". Also available @ publications.gbdirect.co.uk/c_book/chapter5/pointers.html
    • exebook
      exebook over 11 years
      @WhozCraig how about @NULL? NULL is a pointer as well, but is it a variable? How about (char*)55555? Is this a pointer, does it have an address?
    • WhozCraig
      WhozCraig over 11 years
      @exebook NULL is not a pointer. Its technically not even an address.
    • exebook
      exebook over 11 years
      @WhozCraig why do they call it "null pointer exception" then?
    • WhozCraig
      WhozCraig over 11 years
      @d0rmLife Yeah, i think that author needs to step back and climb down from the pillar.His logic for continuing usage of a term he so freshly assailed earlier is laughable. And as far as definition is concerned: C99 6.5.3.2,p3: The unary & operator yields the address of its operand." The type of address returned is specific to the variable to which it is applied, but it is no mistake the standard uses that language.
    • Rad'Val
      Rad'Val over 11 years
      @exebook you're confused. All your examples have an address. Where and how, that's a different discussion. And yes, pointers have addresses.
    • WhozCraig
      WhozCraig over 11 years
      The author could have made a helluva case for confusion between addresses and the variables that hold them (i.e. pointers) just by dissecting exebook's comments in this question.
    • thang
      thang over 11 years
      why is it that every answer assumes that a memory address is an integer... where does it say that this needs to be true? there is something more profound in a pointer that makes it not an address beyond the fact that it doesn't need to be an integer.
    • Alexey Frunze
      Alexey Frunze over 11 years
      The ultimate reputable source is the language standard and not books semi-derived from it and semi-pulled-from-the-author's-butt. I learned it the hard way, making almost every mistake I could and slowly building a mental model of C somewhat close that of described by the standard and then finally replacing said model with the standard's model.
    • exebook
      exebook over 11 years
      I wish language standards were written so newbies can learn language using them. Now you can usually only relearn language you already know by reading standards.
    • Alexey Frunze
      Alexey Frunze over 11 years
      @thang People think pointer=integer because it is often so (x86 Linux and Windows "teach" us that), because people love generalizing, because people don't know the language standard well and because they've had little experience with radically different platforms. Those same people are likely to assume that a pointer to data and a pointer to a function can be converted to one another and data can be executed as code and code be accessed as data. While this may be true on von Neuman architectures (with 1 address space), but not necessarily true on Harvard architectures (w/ code & data spaces).
    • thang
      thang over 11 years
      @AlexeyFrunze, the question is why is it that every answer assumes that a memory address is an integer, and your answer is People think pointer=integer because it is often. do you see what's wrong here? are you implicitly assuming that pointer=memory address by Gricean...
    • Alexey Frunze
      Alexey Frunze over 11 years
      @exebook Standards are not for newbies (especially, complete ones). They aren't supposed to provide gentle introductions and multitudes of examples. They formally define something, so it can be correctly implemented by professionals.
    • Alexey Frunze
      Alexey Frunze over 11 years
      @thang I think I've made my points clear in my answer and in my comments.
    • Aki Suihkonen
      Aki Suihkonen over 11 years
      A stack pointer is a pointer too, but doesn't have an address. It really boils to that a pointer is a "concept of referring to something with it's address".
    • kutschkem
      kutschkem over 11 years
      NULL is not a valid address, yet NULL can be the value of a pointer variable.
    • LarsH
      LarsH over 11 years
      Several people have declared that a pointer is a variable. Others disagree (@Aki - stack pointer; en.wikipedia.org/wiki/Pointer_%28computer_programming%29 "a data type"). Can someone cite an authoritative reference? Thanks.
    • LarsH
      LarsH over 11 years
      @WhozCraig, any citation to support your initial comment (in particular, the idea that a pointer must be a variable)? Just trying to learn whether this is a few people's opinion or an established fact. For example, man 3 fopen() says that the function returns a FILE pointer, yet obviously it doesn't return a variable. Is the man page wrong?
    • Zach
      Zach over 11 years
      @kutschkem NULL is a valid address on some operating systems (or lack of operating systems). Just because the OS you're on will give you an access violation when attempting to read/write NULL doesn't mean it's not a valid address ever.
    • CiscoIPPhone
      CiscoIPPhone over 11 years
      @Zach According to the standard, deferencing NULL is undefined behavior, in C++ at least: stackoverflow.com/questions/4364536/c-null-reference. Seems a really bad decision to have 0 as a valid pointer.
    • DX-MON
      DX-MON over 11 years
      @CiscoIPPhone When you strip out the operating system, and simply have an address space the size of the number of bits representing all pointer values such as in the Xilinx Microblaze, it doesn't matter where you put things in that space, however NULL can be defined to be 0xFFFFFFFF on that platform if you map nothing to that location in the address space therefore 0 can be a valid pointer as NULL doesn't have to be 0.
    • Peter Mortensen
      Peter Mortensen over 11 years
      Possible duplicate of Pointer implementation details in C
    • Alexey Frunze
      Alexey Frunze about 11 years
      @d0rmLife I think you can now accept an answer. The question's been open for almost two months and has received enough attention.
    • G.Rassovsky
      G.Rassovsky about 9 years
      "The C++ (and C) notion of array and pointer are direct representations of a machine's notion of memory and addresses, provided with no overhead." ~ B. Stroustrup
  • d0rmLife
    d0rmLife over 11 years
    So, the pointee is actually a memory address? You disagree with the author? Just trying to understand.
  • exebook
    exebook over 11 years
    It can confuse even more. Alice, can you see a cat? No I can see only a smile of a cat. So saying that pointer is an address or pointer is a variable that holds an address or saying that pointer is a name of a concept that refers to the idea of an address, how far book writers can go in confusing neeeewbies?
  • Aniket Inge
    Aniket Inge over 11 years
    @exebook to those seasoned in pointers, it is quite simple. Maybe a picture will help?
  • Alexey Frunze
    Alexey Frunze over 11 years
    In a C interpreter, a pointer may hold a non-address ID/handle/etc.
  • Alexey Frunze
    Alexey Frunze over 11 years
    The primary function of the pointer is to point to something. How exactly that is achieved and whether there is a real address or not, is not defined. A pointer could be just an ID/handle, not a real address.
  • Alexey Frunze
    Alexey Frunze over 11 years
    A pointer does not necessarily hold an address. In a C interpreter, it could be something else, some kind of ID/handle.
  • d0rmLife
    d0rmLife over 11 years
    Could explain a little bit about handlers/ID's? I think that will help my understanding. I haven't come across those terms until now!
  • Alexey Frunze
    Alexey Frunze over 11 years
    Generally, it's a handle/ID. Usually, it's a plain address.
  • Alexey Frunze
    Alexey Frunze over 11 years
    There's not much to explain. Every variable has its address in memory. But you don't have to store their addresses in pointers to them. Instead you can number your variables from 1 to whatever and store that number in the pointer. That is perfectly legal per the language standard so long as the implementation knows how to transform those numbers into addresses and how to do pointer arithmetic with those numbers and all other things required by the standard.
  • Matthew Sanders
    Matthew Sanders over 11 years
    I adjusted my answer to be a bit more PC to the definition of Handle in wikipedia. I like to refer to pointers as a particular instance of a handle, as a handle may simply be a reference to a pointer.
  • Alexey Frunze
    Alexey Frunze over 11 years
    Not necessarily an address. Btw, did you read existing answers and comments before posting your answer?
  • thang
    thang over 11 years
    PC... flat memory model? what are selectors?
  • exebook
    exebook over 11 years
    sounds nice but how about this then: int i = 555, *p = &i; p++; // this is valid C and valid C++ and will work only if pointers are adresses.
  • thang
    thang over 11 years
    i would like to add that on x86, a memory address consists of a segment selector and an offset, so representing a pointer as segment:offset is still using memory address.
  • exebook
    exebook over 11 years
    C interpreter is not C language described by standard. It's "interpreted-C" which is different animal, and non-standartized as much as I know.
  • Alexey Frunze
    Alexey Frunze over 11 years
    @thang That's fine, but such a pair of values is not a simple single integer address anymore.
  • Cornstalks
    Cornstalks over 11 years
    @AlexeyFrunze: I added a (lengthy) expansion on your comment. Feel free to critique.
  • thang
    thang over 11 years
    @AlexeyFrunze, it's not an integer, but it's still an address. where do you all of a sudden get "integer address" from? it's also not a potato, but i don't care that it's not a potato.
  • Alexey Frunze
    Alexey Frunze over 11 years
    @exebook The standard is not anyhow limited to compiled C.
  • Alexey Frunze
    Alexey Frunze over 11 years
    @thang It's an x86 address, yes.
  • Rad'Val
    Rad'Val over 11 years
    @thang how is the selector and offset stored? It's still an integer value right? Although it doesn't directly represent an address
  • thang
    thang over 11 years
    @ValentinRadu you may argue that it is two integers because it doesn't express the ordering property of integers. otherwise, you can say that any data is an integer, albeit a very large one. a 5 mb file contains one very big integer...
  • Lundin
    Lundin over 11 years
    The C standard may not mention what a pointer is, but in reality a pointer is either an integer containing an absolute address, or an integer containing a virtual address, in case the CPU/OS supports that concept. No other implementation of pointers exists, or is likely to ever exist. So to think of pointers as "fuzzy entities" will not be of help to anyone, certainly not to a beginner.
  • Alexey Frunze
    Alexey Frunze over 11 years
    @Lundin I agree with the last sentence in terms of understanding the concept. However, likely/unlikely is exactly fuzzy and that's the whole point, the pointer is fuzzy per the standard. Obviously, it's not fuzzy in, say, gcc targetting x86 CPUs in 32-bit or 64-bit modes.
  • Alexey Frunze
    Alexey Frunze over 11 years
    So, who's the higher authority than the C standard that feels that the C standard is wrong along with my restatement of its treatment of pointers? Be ashamed of downvoting.
  • Lundin
    Lundin over 11 years
    Is it meaningful though, to pretend that a pointer can store some sort of "ID"? Because in the cold harsh reality outside ISO 9899, no such implementations exist. Pointers are implemented as a variable containing an address, in raw integer format, on 100% of the existing computer systems in the real world. There are some cases where you should just ignore the standard, because it is needlessly generic.
  • Lundin
    Lundin over 11 years
    As I wrote in a comment to another answer, there are cases where you should just ignore the C standard, because it is too generic. This is one such example, another example is the implementation of signed numbers. It does you no good in the real world to believe that pointers are "fuzzy entities", nor does it do you any good to go ask for a "sign & magnitute CPU" in your computer store.
  • Lundin
    Lundin over 11 years
    One has to be aware that ISO places restrictions on a standard, saying that it may not favour one existing technique on the market in front of another, it must be impartial and not favour a particular company. So ISO C cannot take sides in little VS big endian, it can not state that two's complement is universal because some hobo computer from the 70s had one's complement, and so on. We humans in the real world outside ISO should maintain a sober approach though. The C standard is not a holy book.
  • Alexey Frunze
    Alexey Frunze over 11 years
    @Lundin Bravo! Let's ignore the standard more! As if we haven't ignored it enough already and haven't produced buggy and poorly portable software because of it. Also, please not that the original question is generic and as such needs a generic answer.
  • Alexey Frunze
    Alexey Frunze over 11 years
    @Lundin I have no problems ignoring the generic nature of the standard and the inapplicable when I know my platform and my compiler. The original question is generic, however, so you can't ignore the standard when answering it.
  • Lundin
    Lundin over 11 years
    The OP is obviously a beginner and not a computer scientist busy inventing some new, revolutionary pointer implementation. So for the sake of pedagogy, I believe that the C standard should be ignored.
  • Lie Ryan
    Lie Ryan over 11 years
    @exebook: it's valid, but accessing *p will be undefined behavior. There is nothing in the standard that says *p will then point to anything useful; it's like accessing an out-of-bounds array.
  • Alexey Frunze
    Alexey Frunze over 11 years
    @Lundin You don't need to be revolutionary or a scientist. Suppose you want to emulate a 32-bit machine on a physical 16-bit machine and you extend your 64KB of RAM to up to 4GB by using disk storage and implement 32-bit pointers as offsets into a huge file. Those pointers aren't real memory addresses.
  • Lundin
    Lundin over 11 years
    @AlexeyFrunze I'm actually a firm believer of standard compliance and preach it whenever I get a chance. But you can't blindly accept everything in the standard, you need to use rational thinking and question if it applies to the real world. I have vast experience of reading and interpreting boring technical standards and the same applies to every single one of them. If you can conclude that the standard says something, but it doesn't make sense in the real world, you address this in documentation and ignore the standard. Any 3rd party notified body reviewing your product will accept such.
  • Lundin
    Lundin over 11 years
    @AlexeyFrunze Indeed they aren't, they are either virtual addresses, that behaves in the same manner as far as the C programmer is concerned, or they are non-standard extended addresses, "far pointers". The compiler implementation for such a system will have to make the translation between physical addresses and pointer variables in the C program. Because if the (contents of) pointers don't behave as addresses, then pointer arithmetic and indirect addressing will fail and the C program will turn useless.
  • Grijesh Chauhan
    Grijesh Chauhan over 11 years
    @AlexeyFrunze that ID is actually called Logical address. Correct?
  • kutschkem
    kutschkem over 11 years
    +1 for pointing out pointer arithmetic is not the same as arithmetic on addresses.
  • Samuel Edwin Ward
    Samuel Edwin Ward over 11 years
    @Lundin, what do you think about the notes about the Renesas D10V here? Are you arguing that these are addresses in raw integer format or that the D10V doesn't exist?
  • Eric Postpischil
    Eric Postpischil over 11 years
    When others are saying that a pointer might be a handle or something else other than an address, they do not just mean that you can coerce data into a pointer by casting an integer into a pointer. They mean the compiler might be using something other than memory addresses to implement pointers. On the Alpha processor with DEC’s ABI, a function pointer was not the address of the function but was the address of a descriptor of a function, and the descriptor contained the address of the function and some data about the function parameters. The point is that the C standard is very flexible.
  • Lundin
    Lundin over 11 years
    @SamuelEdwinWard There are plenty of odd cases where a program cannot address physical memory directly, for various reasons, but uses some virtual addressing scheme instead. See my latest comment below Alexey's answer.
  • Eric Postpischil
    Eric Postpischil over 11 years
    @Lundin: The assertion that pointers are implemented as integer addresses on 100% of the existing computer systems in the real world is false. Computers exist with word addressing and segment-offset addressing. Compilers still exist with support for near and far pointers. PDP-11 computers exist, with RSX-11 and the Task Builder and its overlays, in which a pointer must identify the information needed to load a function from disk. A pointer cannot have the memory address of an object if the object is not in memory!
  • Mr.Mindor
    Mr.Mindor over 11 years
    @Samuel It seems they are still integers, and they still point to memory addresses. Just some point to byte address and some point to word address. I'm not sure about Lundin's claim, but this isn't a counterexample. I once worked with a microprocessor that had completely separate data and code memory, each starting at 0x0000. you could not interchange the pointers, but they were still integers. D10V appears to be the same way... you can not interchange the pointers, but they are still integers.
  • Ben
    Ben over 11 years
    The "label" or variable name is a compiler/assembler and doesn't exist at the machine level so I don't think it should appear in the memory.
  • Samuel Edwin Ward
    Samuel Edwin Ward over 11 years
    @Mr.Mindor floating point numbers are integers too if you feel like it. But to say I can have two pointers to the same piece of memory, and they are both just integers, and the values of those integers aren't the same... what's the point of even saying they're integers at that point?
  • vonbrand
    vonbrand over 11 years
    In the case of the 16-bit 8086, a memory address is described by a segment base + offset, both 16 bits. There are many combinations of segment base + offset that give the same address in memory. This far pointer isn't just "an integer".
  • vonbrand
    vonbrand over 11 years
    Riight. And when the next architecture change comes around, perhaps with separate code adn data spaces, or someone goes back to the venerable segment architecture (which makes tons of sense for security, might even add some key to segment number + offset to check permissions) your lovely "pointers are just integers" comes crashing down.
  • Andrey
    Andrey over 11 years
    If it can theoretically be anything, how would pointers arithmetics work? Like somePointer + 1 or pointerA - pointerB, afaik standard says that difference of pointers must be int, no?
  • d0rmLife
    d0rmLife over 11 years
    I like your explanation on the abstract reality of a general pointer in a general system. But, perhaps discussing memory would be helpful. In fact, speaking for myself, I know it would...! I think discussing the connection can be very helpful for understanding the big picture. +1 anyways :)
  • Abhijit
    Abhijit over 11 years
    @d0rmLife: You have enough explanation in the other answers which covers the bigger picture. I just wanted to give a mathematical abstract explanation as an another view. Also IMHO, it would create less confusion in calling & as 'Address of` as that is more tied to an Object rather than the pointer per se`
  • d0rmLife
    d0rmLife over 11 years
    No offense, but I will decide for myself what sufficient explanation is. One textbook is not sufficient to fully explain data structures and memory allocation. ;) .... anyways, your answer is still helpful, even if it isn't novel.
  • undur_gongor
    undur_gongor over 11 years
    +1. Other answers seem to miss that a pointer comes with type information. This is far more important than the address/ID/whatever discussion.
  • LarsH
    LarsH over 11 years
    "A pointer is a variable that HOLDS memory address, not the address itself" - really? linux.die.net/man/3/fopen says that fopen() returns a FILE pointer. Does fopen() return a variable?
  • LarsH
    LarsH over 11 years
    +1 Excellent points about type information. I'm not sure the compiler examples are correct tho... It seems very unlikely, for example, that *p = 3 is guaranteed to succeed when p has not been initialized.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 11 years
    @LarsH You're right, thanks, how did I write that? I replaced it by an example that even demonstrates the surprising behavior on my PC.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 11 years
    A pointer holds an address (or doesn't, if it's null). But that's a far cry from it being an address: for example, two pointers to the same address but with a different type are not equivalent in many situations.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 11 years
    No, it's not that simple. For a start, a null pointer doesn't hold an address. More importantly, you can have two pointers that hold the same address, but behave differently (my answer goes into more detail).
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 11 years
    Not only does this not address the notion of address as opposed to pointer, but it integrally misses the point that an address is not just an integer.
  • Rad'Val
    Rad'Val over 11 years
    @Gilles If you see "being", as in int i=5-> i is 5 then, the pointer is the address yes. Also, null has an address as well. Usually an invalid write address (but not necessarily, see x86-real mode), but an address none the less. There are really only 2 requirements for null: it's guaranteed to compare unequal to a pointer to an actual object and any two null pointers will compare equal.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 11 years
    On the contrary, a null pointer is guaranteed not to be equal to the address of any object. Dereferencing a null pointer is undefined behavior. A big problem with saying that “the pointer is the address” is that they work differently. If p is a pointer, p+1 is not always the address incremented by 1.
  • Rad'Val
    Rad'Val over 11 years
    Read again the comment please, it's guaranteed to compare unequal to a pointer to an actual object. As for the pointer arithmetics, I don't see the point, the value of the pointer is still an address, even if the "+" operation will not necessarily add one byte to it.
  • alexis
    alexis over 11 years
    -1, this just explains what a pointer is. That was not the question-- and you're pushing aside all the complexities that the question is about.
  • Russell Borogove
    Russell Borogove over 11 years
    @Lundin, other implementations of pointers do exist, although they aren't common on popular modern platforms. See c-faq.com/null/machexamp.html.
  • Russell Borogove
    Russell Borogove over 11 years
    @Andrey, the compiler has to do object-size fixup when subtracting pointers (it has to give you the difference in number of elements, not number of bytes), so we already know that pointer arithmetic isn't integer arithmetic.
  • Aniket Inge
    Aniket Inge over 11 years
    um, NULL is ((void *)0) .. ?
  • DX-MON
    DX-MON over 11 years
    NULL pointers don't work the way you think they do on all platforms - please see my reply to CiscoIPPhone above. NULL == 0 is an assumption that only holds on x86 based platforms. Convention says that new platforms should match x86, however particularly in the embedded world this is not so. Edit: Also, C does nothing to abstract the value of a pointer way from hardware - "ptr != 0" will not work as a NULL test on a platform where NULL != 0.
  • csakii
    csakii over 11 years
    DX-MON, that's completely wrong for standard C. NULL is devined to be 0, and they can be used interchangeably in statements. Whether on not the NULL pointer representation in hardware is all 0 bits is irrelevant to how it's represented in source code.
  • Kaz
    Kaz over 11 years
    @DX-MON I'm afraid you are not working with the correct facts. In C, an integral constant expression serves as a null pointer constant, regardless of whether the null pointer is the null address. If you know of a C compiler where ptr != 0 is not a null test, please reveal its identity (but before you do that, send a bug report to the vendor).
  • Aniket Inge
    Aniket Inge over 11 years
    @LarsH is pointer an address or a variable that holds address? With fopen() lets say an address was returned from it, where do you put the address? can you use the return value from fopen() without putting the "address" it returned into a FILE * object?
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 11 years
    @Aniket A pointer variable can contain a pointer value. You only need to store the result of fopen into a variable if you need to use it more than once (which, for fopen, is pretty much all the time).
  • LarsH
    LarsH over 11 years
    @Aniket: a pointer value is returned. You can put it in a pointer variable if you want, or you could pass it directly to fclose(). You normally would put it in a variable, but you don't have to.
  • Eric Postpischil
    Eric Postpischil over 11 years
    One point I do not see made yet is that, if you attempt to use pointers as if they were addresses, in ways not defined by the C standard, the compiler may produce strange results when optimization is applied. As an example, suppose you have struct { int a[4], b; } x;. Although b must be immediately after a in the struct, the optimizer may conclude that *(a+4) is not a reference to b, because *(x.a+4) is not a valid way to refer to b. Therefore, code such as x.b = 3; *(x.a+4) = 5; printf("%d", x.b); may print “3” even though it would be “5” if pointers were just addresses.
  • Aki Suihkonen
    Aki Suihkonen over 11 years
    It makes no sense to handle pointers without the concept of memory. If the object exists without memory, it must be in a place, where there is no address -- e.g. in registers. To be able to use '&' presupposes memory.
  • Aki Suihkonen
    Aki Suihkonen over 11 years
    +1 Thank you. With pointers, value and type are as inseparable as one can separate mans body from his soul.
  • alexis
    alexis over 11 years
    I see what you're getting at, but your comments about null pointers are incoherent because you're confusing pointers and memory addresses-- exactly what the quote cited in the question advises avoiding! The correct statement: C defines the null pointer to be zero, regardless of whether a memory address at offset zero is legal or not.
  • alexis
    alexis over 11 years
    "If a float *p pointer points to a long n variable, and *p = 0.0 is executed, the compiler is not required to handle this." What do you mean? Aliasing problems result from (non-omniscient) optimization; they have nothing to do with the type of the pointed-to variable, or with the address-pointer relationship really.
  • Kaz
    Kaz over 11 years
    @alexis Chapter and verse, please. C does not define the null pointer to be zero. C defines zero (or any integral constant expression whose value is zero) as a syntax for denoting a null pointer constant. faqs.org/faqs/C-faq/faq (section 5).
  • Kaz
    Kaz over 11 years
    @alexis Yes, aliasing is connected to type, in the following way. C forbids most instances of type-punned aliasing, and that allows for aggressive optimizations. If an object of type int is assigned to, the compiler doesn't have to be concerned that the assignment might modify anything that has type double (a situation which can only happen via some kind of aliasing). Of course, aliasing can take place when the type is the same also, e.g. aliased arrays. There are different issues there, but related.
  • Mr.Mindor
    Mr.Mindor over 11 years
    @SamuelEdwinWard Because they still are. I'm not claiming that the fact they are integers is useful in the way you seem to want it to be, just that your example of a system where the integer value is interpreted differently depending on the pointer type doesn't refute Lundin's claim that pointers are integers which point to an address in all implementations (which, btw I'm not espousing).
  • Barmar
    Barmar over 11 years
    The best example I've ever seen of this was the C implementation for Symbolics Lisp Machines (circa 1990). Each C object was implemented as a Lisp array, and pointers were implemented as a pair of an array and an index. Because of Lisp's array bounds checking, you could never overflow from one object to another.
  • alexis
    alexis over 11 years
    @Kaz, you're right that my formulation was oversimplified: It's not about what the null pointer "is", meaning its internal storage representation. You get a null pointer by setting it to zero, the null pointer constant, and it compares equal to zero, so as far as C is concerned, it is zero-- actually I think your answer makes pretty much the same point, but from a different perspective. (In other words: I'm not saying you're factually wrong, but I'd draw a very different distinction).
  • thang
    thang over 11 years
    @vonbrand i don't understand why you posted that comment. that issue has been discussed as comments under other answers. just about every other answer assumes that address = integer and anything not integer is not address. i simply point this out and note that it may or may not be correct. my whole point in the answer is that it is not relevant. it's all just pedantic, and the main issue is not being addressed in the other answers.
  • vonbrand
    vonbrand over 11 years
    @tang, the idea "pointer == address" is wrong. That everybody and their favorite aunt continue saying so doesn't make it right.
  • thang
    thang over 11 years
    @vonbrand, and why did you make that comment under my post? I didn't say it is either right or wrong. In fact, it is right in certain scenarios/assumptions, but not always. Let me summarize again the point of the post (for the second time). my whole point in the answer is that it is not relevant. it's all just pedantic, and the main issue is not being addressed in the other answers. it would be more appropriate to comment on the answers that do make the claim that pointer==address or address==integer. see my comments under Alexey's post with respect to segment:offset.
  • thang
    thang over 11 years
    and by the way, that there's a ton of answers that are mostly wrong, inaccurate, incomplete, and totally miss the point is out of my control. And furthermore, that they get up voted is also out of my control. I have commented on them to clarify the issue before writing this answer.
  • Kaz
    Kaz over 11 years
    @alexis A null pointer does not compare equal to zero. It compares equal to a null pointer constant, which is only notated by an integral zero at compile time. A null pointer is not equal to an int type variable whose value is zero. Such a comparison requires a diagnostic. So no, a null pointer is not zero as far as C is concerned.
  • DX-MON
    DX-MON over 11 years
    @Kaz so in that case, how the hell on an embedded system would you dereference memory address 0? Cast a long set to 0 to a pointer? I think you'll find that if you try any of that sort of funk with the Xilinx version of GCC, NULL will be set to something more sensible for the platform such as 0xFFFFFFFF as that is usually an unused and therefore invalid address in the processor memory address map of a Microblaze. Memory address zero is actually surprisingly important on a Microblaze due to the interrupt vector system, not being able to access it sounds like an immediate "shot in foot"
  • Aniket Inge
    Aniket Inge over 11 years
    Just when you think you know a concept in C pretty well - out comes an answer on SO or in the standards that defy and destroy everything you thought was right. A person can never fully learn C until he has studied the standards. +1 sir, excellent accuracy of understanding and enlightened soul :-)
  • Alexey Frunze
    Alexey Frunze about 11 years
    In 16 bit real mode LinearAddress = SegmentRegister.Selector * 16 + Offset (note times 16, not shift by 16). In protected mode LinearAddress = SegmentRegister.base + offset (no multiplication of any kind; the segment base is stored in the GDT/LDT and cached in the segment register as is).
  • Krazy Glew
    Krazy Glew about 11 years
    You are also correct about the segment base. I had misremembered. It is the segment limit that is optionally multiple by 4K. he segment base just needs to be unscrambled by the hardware when it loads a segment descriptor from memory into a segment register.
  • Lorenzo Donati support Ukraine
    Lorenzo Donati support Ukraine almost 11 years
    @Mr.Mindor Technically not, IMO, because the content of a memory location (or a memory word), is not in itself an integer, it is a sequence of bytes, whose interpretation as integers (or pointers, or FP numbers) is not absolute, but depends on the operations you perform on them. Take a memory-mapped 8-bit register of some digital I/O card, for example, and suppose the single bits represent the state of some external lines. Is it meaningful to call the content of that memory location an integer? Every single bit is completely independent, so how can they be interpreted as a number?
  • Tony Delroy
    Tony Delroy about 10 years
    @EricPostpischil what your example illustrates is that the language doesn't oblige the compiler to correctly identify such abuses, so it may use a value based on static analysis or from a register it used to load x.b without reloading the memory address (unless a and b are volatile) - all that's got absolutely nothing to do with whether "pointers [are] just addresses".
  • gnasher729
    gnasher729 about 10 years
    In many implementations, NULL is not a null pointer. It isn't even a pointer. #define NULL (1312-1200-112ull) would be a perfectly fine definition for NULL. NULL is required to be a macro that evaluates to a null pointer constant and in certain situations, null pointer constants are automatically converted to null pointers.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' about 10 years
    @gnasher729 The null pointer is a pointer. NULL isn't, but for the level of detail required here, this is an irrelevant distraction. Even for day-to-day programming, the fact that NULL may be implemented as something that doesn't say “pointer” doesn't come up often (primarily passing NULL to a variadic function — but even there, if you aren't casting it, you're already making the assumption that all pointer types have the same representation).
  • jds
    jds over 9 years
    This answers the question. A pointer is not an address; it is a language abstraction of an address.
  • Steve Jessop
    Steve Jessop over 9 years
    At great overhead, maybe you could detect any use of the pointer value that might "leak" its numeric value, and pin the allocation so that the garbage collector won't collect or relocate it (unless free is called explicitly, of course). Whether the resulting implementation would be all that useful is another matter, since its ability to collect might be too limited, but you could at least call it a garbage collector :-) Pointer assignment and arithmetic wouldn't "leak" the value, but any access to a char* of unknown origin would have to be checked.
  • supercat
    supercat over 9 years
    @SteveJessop: I think such a design would be worse than useless, since it would be impossible for code to know what pointers needed to be freed. Garbage-collectors that assume anything that looks like a pointer is one may be overly conservative, but generally things that look like--but aren't--pointers have a possibility of changing, thus avoiding "permanent" memory leaks. Having any action that looks like it's decomposing a pointer to bytes permanently freeze the pointer is a guaranteed recipe for memory leaks.
  • Steve Jessop
    Steve Jessop over 9 years
    I think it would fail anyway for performance reasons -- if you want your code to run that slowly because every access is checked then don't write it in C ;-) I have higher hopes for the ingenuity of C programmers than you do, since I think while inconvenient it's probably not implausible to avoid pinning allocations unnecessarily. Anyway, C++ defines "safely derived pointers" precisely in order to deal with this issue, so we know what to do if we ever want to increase the abstractness of C pointers to the level where they support reasonably effective garbage collection.
  • supercat
    supercat over 9 years
    @SteveJessop: For a GC system to be useful, it should either be able to reliably release memory upon which free has not been called, or prevent any reference to a freed object from becoming a reference to a live object [even when using resources that require explicit lifetime management, GC can still usefully perform the latter function]; a GC system which sometimes falsely regard objects as having live references to them may be usable if the probability of N objects being needlessly pinned simultaneously approaches zero as N gets large. Unless one is willing to flag a compiler error...
  • supercat
    supercat over 9 years
    ...for code which is valid C++, but for which the compiler would be unable to prove that a pointer can never get converted into an unrecognizable form, I don't see how one could avoid the risk that a program which in fact never uses pointers as integers might be falsely regarded as doing so.
  • Kaz
    Kaz over 9 years
    @DX-MON Dereferencing memory address 0 is outside of portable C. Typically, you would do it like this: TYPE *ptr = (TYPE *) 0 and then later *ptr. That depends on the null pointer corresponding to address zero. But that dependency is true of your embedded system. The code is portable only to that system anyway, so everything is cool. If (TYPE *) 0 produced the address 0x7FFFFFFF or whatever, then you'd be on a different system where you'd have a workaround for that, like using a non-constant zero: int zero = 0; TYPE *p = (TYPE *) zero.
  • Steve Jessop
    Steve Jessop over 9 years
    For a GC system to be useful it has to be able to collect a subset of objects which the programmer ensures are collectible, by treating them carefully. For it to be extremely useful, in the way that the Java GC is useful, it does that even for carelessly-treated objects ;-) There are many programs in which it would be simple to ensure that for some entity type, its objects' addresses are never "leaked", but difficult (or impossible) for the compiler to know that this is what the programmer has ensured.
  • supercat
    supercat over 9 years
    @SteveJessop: It might be possible in C++ to have a form of GC in which every GC object encapsulated some primitives and some GC references, and in which all GC references not held within GC objects had to be held in lifetime-managed objects [every "outside-reference" object would be considered a GC root; failing to call the destructor of an "outside" GC reference would leak that object and all objects directly or indirectly referenced thereby]. The thing I don't know is how well one could avoid having a statement like foo->ref1 = bar->ref2 [where foo and bar are both OutsideGcRef]...
  • supercat
    supercat over 9 years
    ...need to construct an OutsideGcRef to hold the reference temporarily. Ideally, the type of bar->ref2 would not be constructable except by the GC, but would be convertible to an OutsideGcRef, and would override the assignment operator so as to copy the reference directly without having to create an OutsideGcRef first.
  • M.M
    M.M over 9 years
    i == c is ill-formed (you can only compare pointers to different types if there is an implicit conversion from one to the other). Further, fixing this with a cast means you have applied a conversion, and then it's debatable whether the conversion changes the value or not. (You could assert that it doesn't, but then that is just asserting the same thing that you were trying to prove with this example).
  • M.M
    M.M over 9 years
    @AlexeyFrunze it seems hard to argue with the Standard quote The unary & operator yields the address of its operand. If the operand has type ‘‘type’’, the result has type ‘‘pointer to type’’. This implies that the value stored in a pointer is the address of the thing being pointed to. There cannot be a "non-address" stored in a pointer. The C interpreter you refer to would represent its addresses in textual form or whatever.
  • Jeff Hammond
    Jeff Hammond about 9 years
    NULL compares equal to zero. That is different from (void*)0.
  • David Schwartz
    David Schwartz about 4 years
    @exebook "sounds nice but how about this then: int i = 555, *p = &i; p++; // this is valid C and valid C++ and will work only if pointers are adresses." I'm a bit late to the party, but this comment is wrong. That will work whatever pointers are. There is no rule that p++ must add some fixed amount to p. It could, for example, figure out the ID of the next object in the array that p currently holds the ID to an object in.
  • cubuspl42
    cubuspl42 over 3 years
    @AlexeyFrunze While this interpretation makes a lot of sense, I don't understand how such interpretation (that pointer is not an address) work with alignment. C standard defines alignment as "requirement that objects of a particular type be located on storage boundaries with addresses that are particular multiples of a byte address". If pointers aren't thought as entities that hold addresses, alignment doesn't seem to make any sense at all.
  • Alexey Frunze
    Alexey Frunze over 3 years
    @cubuspl42 Alignment may be optional. But we can go deeper even without touching alignment. We are allowed to access every C byte in everything through a pointer to a char (unsigned char is safest). And we're allowed to make a pointer beyond the last array element and the same is allowed with non-arrays. So, that kinda asks for pointers to really be addresses since it would be easy to access adjacent things by doing pointer arithmetic. However, there's no pointer arithmetic on things that aren't part of the same larger thing (e.g. separate variables or malloc()'d regions).
  • Alexey Frunze
    Alexey Frunze over 3 years
    @cubuspl42 So, addresses need not be true and universal representation of pointers. And like I said earlier, they can really be locations in something else, e.g. a file and not memory.
  • cubuspl42
    cubuspl42 over 3 years
    @AlexeyFrunze Without bringing the alignment to the table, I'm still convinced by your original explanation. The ability of interpreting every object as a byte array means just that all objects (that are separate by nature) are built of bytes, and you can read their bytes as (unsigned) char even if the object's effective type is not (unsigned) char or an array of (unsigned) chars. They can still live in an abstract set of objects, no addressable memory involved. Pointers can point to these objects; if they're arrays, you can iterate that array with a pointer.
  • cubuspl42
    cubuspl42 over 3 years
    You can search the standard for the word "address". In my copy (n1570 draft), there're just 79 occurrences. More or less half of it are uses in the context of alignment (and those uses imply that objects live in an addressable linear memory built of bytes, and those addresses can be a multiply of something) and the other half uses the word "address" as a synonym to "pointer" or something that a pointer holds.
  • cubuspl42
    cubuspl42 over 3 years
    So, basically, I'm just saying that I like your answer and the explanation it contains, because standard doesn't say pointers per se are addresses. But in context of alignment, standard does say (or at least strongly imply) that "address" = "linear memory address" and then in other parts effectively state that "address" = "pointer". So, effectively, "pointer" = "memory address".
  • cubuspl42
    cubuspl42 over 3 years
    I don't mean that "memory" has to mean assembly level address to a virtual or physical memory / RAM. Of course it still doesn't rule out a file-based implementation, or an interpreter. But, at least for C11, I believe you'll be right to think that a pointer holds a (some-kind-of-) memory address, or at least a "data storage" address (which is a synonym for some kind of linear memory).