What exactly is a C pointer if not a memory address?
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
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 ofx
then the expression*p
has the same value asx
); - 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.
A program to demonstrate what I am saying and its output is here:
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;
}
Related videos on Youtube
d0rmLife
Updated on July 17, 2022Comments
-
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 over 11 yearsA 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 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 over 11 years
-
Cornstalks over 11 yearsWhat's your "reputable source" for the quote?
-
exebook over 11 yearsPointer 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 over 11 years@exebook pointer has an address because the pointer is also a variable that is holding an address.
-
WhozCraig over 11 years@exebook Really? pointer has no address? Mkk.
int *p = NULL, **pp = &p;
So much for that. -
d0rmLife over 11 years@Cornstalks Mike Banahan, author of "The C Book". Also available @ publications.gbdirect.co.uk/c_book/chapter5/pointers.html
-
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 over 11 years@exebook NULL is not a pointer. Its technically not even an address.
-
exebook over 11 years@WhozCraig why do they call it "null pointer exception" then?
-
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 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 over 11 yearsThe 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 over 11 yearswhy 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 over 11 yearsThe 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 over 11 yearsI 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 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 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 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 over 11 years@thang I think I've made my points clear in my answer and in my comments.
-
Aki Suihkonen over 11 yearsA 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 over 11 yearsNULL is not a valid address, yet NULL can be the value of a pointer variable.
-
LarsH over 11 yearsSeveral 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 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 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 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 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 over 11 yearsPossible duplicate of Pointer implementation details in C
-
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 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 over 11 yearsSo, the pointee is actually a memory address? You disagree with the author? Just trying to understand.
-
exebook over 11 yearsIt 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 over 11 years@exebook to those seasoned in pointers, it is quite simple. Maybe a picture will help?
-
Alexey Frunze over 11 yearsIn a C interpreter, a pointer may hold a non-address ID/handle/etc.
-
Alexey Frunze over 11 yearsThe 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 over 11 yearsA pointer does not necessarily hold an address. In a C interpreter, it could be something else, some kind of ID/handle.
-
d0rmLife over 11 yearsCould 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 over 11 yearsGenerally, it's a handle/ID. Usually, it's a plain address.
-
Alexey Frunze over 11 yearsThere'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 over 11 yearsI 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 over 11 yearsNot necessarily an address. Btw, did you read existing answers and comments before posting your answer?
-
thang over 11 yearsPC... flat memory model? what are selectors?
-
exebook over 11 yearssounds 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 over 11 yearsi 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 over 11 yearsC 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 over 11 years@thang That's fine, but such a pair of values is not a simple single integer address anymore.
-
Cornstalks over 11 years@AlexeyFrunze: I added a (lengthy) expansion on your comment. Feel free to critique.
-
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 over 11 years@exebook The standard is not anyhow limited to compiled C.
-
Alexey Frunze over 11 years@thang It's an x86 address, yes.
-
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 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 over 11 yearsThe 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 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 over 11 yearsSo, 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 over 11 yearsIs 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 over 11 yearsAs 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 over 11 yearsOne 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 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 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 over 11 yearsThe 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 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 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 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 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 over 11 years@AlexeyFrunze that ID is actually called Logical address. Correct?
-
kutschkem over 11 years+1 for pointing out pointer arithmetic is not the same as arithmetic on addresses.
-
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 over 11 yearsWhen 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 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 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 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 over 11 yearsThe "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 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 over 11 yearsIn 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 over 11 yearsRiight. 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 over 11 yearsIf it can theoretically be anything, how would pointers arithmetics work? Like
somePointer + 1
orpointerA - pointerB
, afaik standard says that difference of pointers must be int, no? -
d0rmLife over 11 yearsI 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 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 over 11 yearsNo 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 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 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. Doesfopen()
return a variable? -
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' 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' over 11 yearsA 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' over 11 yearsNo, 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' over 11 yearsNot 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 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' over 11 yearsOn 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 over 11 yearsRead 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 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 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 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 over 11 yearsum, NULL is ((void *)0) .. ?
-
DX-MON over 11 yearsNULL 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 over 11 yearsDX-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 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 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 fromfopen()
without putting the "address" it returned into aFILE *
object? -
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, forfopen
, is pretty much all the time). -
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 over 11 yearsOne 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;
. Althoughb
must be immediately aftera
in the struct, the optimizer may conclude that*(a+4)
is not a reference tob
, because*(x.a+4)
is not a valid way to refer tob
. Therefore, code such asx.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 over 11 yearsIt 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 over 11 years+1 Thank you. With pointers, value and type are as inseparable as one can separate mans body from his soul.
-
alexis over 11 yearsI 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 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 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 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 typedouble
(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 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 over 11 yearsThe 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 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 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 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 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 over 11 yearsand 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 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 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 over 11 yearsJust 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 about 11 yearsIn 16 bit real mode
LinearAddress = SegmentRegister.Selector * 16 + Offset
(note times 16, not shift by 16). In protected modeLinearAddress = 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 about 11 yearsYou 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 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 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 about 10 yearsIn 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' 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 thatNULL
may be implemented as something that doesn't say “pointer” doesn't come up often (primarily passingNULL
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 over 9 yearsThis answers the question. A pointer is not an address; it is a language abstraction of an address.
-
Steve Jessop over 9 yearsAt 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 achar*
of unknown origin would have to be checked. -
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 over 9 yearsI 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 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 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 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 address0x7FFFFFFF
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 over 9 yearsFor 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 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
[wherefoo
andbar
are bothOutsideGcRef
]... -
supercat over 9 years...need to construct an
OutsideGcRef
to hold the reference temporarily. Ideally, the type ofbar->ref2
would not be constructable except by the GC, but would be convertible to anOutsideGcRef
, and would override the assignment operator so as to copy the reference directly without having to create anOutsideGcRef
first. -
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 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 about 9 yearsNULL compares equal to zero. That is different from (void*)0.
-
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 top
. It could, for example, figure out the ID of the next object in the array thatp
currently holds the ID to an object in. -
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 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 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 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 over 3 yearsYou 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 over 3 yearsSo, 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 over 3 yearsI 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).