What does “dereferencing” a pointer mean?

Multi tool use
Multi tool use


What does “dereferencing” a pointer mean?



Please include an example with the explanation.





this can help you: stackoverflow.com/questions/2795575/…
– Harry Joy
Feb 10 '11 at 9:17





cslibrary.stanford.edu/106
– Erik
Feb 10 '11 at 9:18





int *p; would define a pointer to an integer, and *p would dereference that pointer, meaning that it would actually retrieve the data that p points to.
– Peyman
Feb 10 '11 at 9:21


int *p;


*p





Binky's Pointer Fun (cslibrary.stanford.edu/104) is a GREAT video about pointers that might clarify things. @Erik- You rock for putting up the Stanford CS Library link. There are so many goodies there...
– templatetypedef
Feb 10 '11 at 9:27





Harry's response is the opposite of helpful here.
– Jim Balter
Feb 10 '11 at 9:39




6 Answers
6



It's usually good enough - unless you're programming assembly - to envisage a pointer containing a numeric memory address, with 1 referring to the second byte in the process's memory, 2 the third, 3 the fourth and so on....



When you want to access the data/value in the memory that the pointer points to - the contents of the address with that numerical index - then you dereference the pointer.



Different computer languages have different notations to tell the compiler or interpreter that you're now interested in the pointed-to value - I focus below on C and C++.



Consider in C, given a pointer such as p below...


p


const char* p = "abc";



...four bytes with the numerical values used to encode the letters 'a', 'b', 'c', and a 0 byte to denote the end of the textual data, are stored somewhere in memory and the numerical address of that data is stored in p.


p



For example, if the string literal happened to be at address 0x1000 and p a 32-bit pointer at 0x2000, the memory content would be:


p


Memory Address (hex) Variable name Contents
1000 'a' == 97 (ASCII)
1001 'b' == 98
1002 'c' == 99
1003 0
...
2000-2003 p 1000 hex



Note that there is no variable name/identifier for address 0x1000, but we can indirectly refer to the string literal using a pointer storing its address: p.


p



To refer to the characters p points to, we dereference p using one of these notations (again, for C):


p


p


assert(*p == 'a'); // The first character at address p will be 'a'
assert(p[1] == 'b'); // p[1] actually dereferences a pointer created by adding
// p and 1 times the size of the things to which p points:
// In this case they're char which are 1 byte in C...
assert(*(p + 1) == 'b'); // Another notation for p[1]



You can also move pointers through the pointed-to data, dereferencing them as you go:


++p; // Increment p so it's now 0x1001
assert(*p == 'b'); // p == 0x1001 which is where the 'b' is...



If you have some data that can be written to, then you can do things like this:


int x = 2;
int* p_x = &x; // Put the address of the x variable into the pointer p_x
*p_x = 4; // Change the memory at the address in p_x to be 4
assert(x == 4); // Check x is now 4



Above, you must have known at compile time that you would need a variable called x, and the code asks the compiler to arrange where it should be stored, ensuring the address will be available via &x.


x


&x



In C, if you have a variable that is a pointer to a structure with data members, you can access those members using the -> dereferencing operator:


->


typedef struct X { int i_; double d_; } X;
X x;
X* p = &x;
p->d_ = 3.14159; // Dereference and access data member x.d_
(*p).d_ *= -1; // Another equivalent notation for accessing x.d_



To use a pointer, a computer program also needs some insight into the type of data that is being pointed at - if that data type needs more than one byte to represent, then the pointer normally points to the lowest-numbered byte in the data.



So, looking at a slightly more complex example:


double sizes = { 10.3, 13.4, 11.2, 19.4 };
double* p = sizes;
assert(p[0] == 10.3); // Knows to look at all the bytes in the first double value
assert(p[1] == 13.4); // Actually looks at bytes from address p + 1 * sizeof(double)
// (sizeof(double) is almost always eight bytes)
assert(++p); // Advance p by sizeof(double)
assert(*p == 13.4); // The double at memory beginning at address p has value 13.4
*(p + 2) = 29.8; // Change sizes[3] from 19.4 to 29.8
// Note: earlier ++p and + 2 here => sizes[3]



Sometimes you don't know how much memory you'll need until your program is running and sees what data is thrown at it... then you can dynamically allocate memory using malloc. It is common practice to store the address in a pointer...


malloc


int* p = malloc(sizeof(int)); // Get some memory somewhere...
*p = 10; // Dereference the pointer to the memory, then write a value in
fn(*p); // Call a function, passing it the value at address p
(*p) += 3; // Change the value, adding 3 to it
free(p); // Release the memory back to the heap allocation library



In C++, memory allocation is normally done with the new operator, and deallocation with delete:


new


delete


int* p = new int(10); // Memory for one int with initial value 10
delete p;

p = new int[10]; // Memory for ten ints with unspecified initial value
delete p;

p = new int[10](); // Memory for ten ints that are value initialised (to 0)
delete p;



See also C++ smart pointers below.



Often a pointer may be the only indication of where some data or buffer exists in memory. If ongoing use of that data/buffer is needed, or the ability to call free() or delete to avoid leaking the memory, then the programmer must operate on a copy of the pointer...


free()


delete


const char* p = asprintf("name: %s", name); // Common but non-Standard printf-on-heap

// Replace non-printable characters with underscores....
for (const char* q = p; *q; ++q)
if (!isprint(*q))
*q = '_';

printf("%sn", p); // Only q was modified
free(p);



...or carefully orchestrate reversal of any changes...


const size_t n = ...;
p += n;
...
p -= n; // Restore earlier value...



In C++, it's best practice to use smart pointer objects to store and manage the pointers, automatically deallocating them when the smart pointers' destructors run. Since C++11 the Standard Library provides two, unique_ptr for when there's a single owner for an allocated object...


unique_ptr


{
std::unique_ptr<T> p{new T(42, "meaning")};
call_a_function(p);
// The function above might throw, so delete here is unreliable, but...
} // p's destructor's guaranteed to run "here", calling delete



...and shared_ptr for share ownership (using reference counting)...


shared_ptr


{
std::shared_ptr<T> p(new T(3.14, "pi"));
number_storage.may_add(p); // Might copy p into its container
} // p's destructor will only delete the T if number_storage didn't copy



In C, NULL and 0 - and additionally in C++ nullptr - can be used to indicate that a pointer doesn't currently hold the memory address of a variable, and shouldn't be dereferenced or used in pointer arithmetic. For example:


NULL


0


nullptr


const char* p_filename = NULL; // Or "= 0", or "= nullptr" in C++
char c;
while ((c = getopt(argc, argv, "f:")) != EOF)
switch (c) {
case f: p_filename = optarg; break;
}
if (p_filename) // Only NULL converts to false
... // Only get here if -f flag specified



In C and C++, just as inbuilt numeric types don't necessarily default to 0, nor bools to false, pointers are not always set to NULL. All these are set to 0/false/NULL when they're static variables or (C++ only) direct or indirect member variables of static objects or their bases, or undergo zero initialisation (e.g. new T(); and new T(x, y, z); perform zero-initialisation on T's members including pointers, whereas new T; does not).


0


bools


false


NULL


static


new T();


new T(x, y, z);


new T;



Further, when you assign 0, NULL and nullptr to a pointer the bits in the pointer are not necessarily all reset: the pointer may not contain "0" at the hardware level, or refer to address 0 in your virtual address space. The compiler is allowed to store something else there if it has reason to, but whatever it does - if you come along and compare the pointer to 0, NULL, nullptr or another pointer that was assigned any of those, the comparison must work as expected. So, below the source code at the compiler level, "NULL" is potentially a bit "magical" in the C and C++ languages...


0


NULL


nullptr


0


NULL


nullptr



More strictly, initialised pointers store a bit-pattern identifying either NULL or a (often virtual) memory address.


NULL



The simple case is where this is a numeric offset into the process's entire virtual address space; in more complex cases the pointer may be relative to some specific memory area, which the CPU may select based on CPU "segment" registers or some manner of segment id encoded in the bit-pattern, and/or looking in different places depending on the machine code instructions using the address.



For example, an int* properly initialised to point to an int variable might - after casting to a float* - access a value in "GPU" memory quite distinct from the int variable, then once cast to a function pointer might refer to distinct memory holding the machine opcodes for the function.


int*


int


float*


int



3GL programming languages like C and C++ tend to hide this complexity, such that:



If the compiler gives you a pointer to a variable or function, you can dereference it freely (as long as the variable's not destructed/deallocated meanwhile) and it's the compiler's problem whether e.g. a particular CPU register needs to be restored beforehand, or a distinct machine code instruction used



If you get a pointer to an element in an array, you can use pointer arithmetic to move anywhere else in the array, or even to form an address one-past-the-end of the array that's legal to compare with other pointers to elements in the array (or that have similarly been moved by pointer arithmetic to the same one-past-the-end value); again in C and C++, it's up to the compiler to ensure this "just works"



Specific OS functions, e.g. shared memory mapping, may give you pointers, and they'll "just work" within the range of addresses that makes sense for them



Attempts to move legal pointers beyond these boundaries, or to cast arbitrary numbers to pointers, or use pointers cast to unrelated types, typically have undefined behaviour, so should be avoided in higher level libraries and applications, but code for OSes, device drivers, etc. may need to rely on behaviour left undefined by C or C++, that is nevertheless well defined by their specific hardware.





is p[1] and *(p + 1) identical? That is, Does p[1] and *(p + 1) generate the same instructions?
– Pacerier
Sep 22 '13 at 18:20



p[1]


*(p + 1)


p[1]


*(p + 1)





@Pacerier: from 6.5.2.1/2 in the N1570 draft C Standard (first I found online) "The definition of the subscript operator is that E1[E2] is identical to (*((E1)+(E2)))." - I can't imagine any reason why a compiler wouldn't immediately convert them to identical representations in an early stage of compilation, applying the same optimisations after that, but I don't see how anyone can definitely prove the code would be identical without surveying every compiler ever written.
– Tony Delroy
Sep 23 '13 at 6:51





@TonyD, no I'm not talking about compiler implementations, but rather, did the official standard guarantees that behavior? I mean the latest standards C90, C99, and C11....
– Pacerier
Sep 24 '13 at 4:13





@Honey: the value 1000 hex is too big to encode in a single byte (8 bits) of memory: you can only store unsigned numbers from 0 to 255 in one byte. So, you just can't store 1000 hex at "just" the address 2000. Instead, a 32-bit system would use 32 bits - which is four bytes - with addresses from 2000 to 2003. A 64-bit system would use 64 bits - 8 bytes - from 2000 to 2007. Either way, the base address of p is just 2000: if you had another pointer to p it would have to store 2000 in its four or eight bytes. Hope that helps! Cheers.
– Tony Delroy
Jul 13 '17 at 11:45


p


p





@TonyDelroy: If a union u contains an array arr, both gcc and clang will recognize that the lvalue u.arr[i] might access the same storage as other union members, but will not recognize that lvalue *(u.arr+i) might do so. I'm not sure whether the authors of those compilers think that the latter invokes UB, or that the former invokes UB but they should process it usefully anyway, but they clearly view the two expressions as different.
– supercat
Jun 29 at 20:58


u


arr


u.arr[i]


*(u.arr+i)



Dereferencing a pointer means getting the value that is stored in the memory location pointed by the pointer. The operator * is used to do this, and is called the dereferencing operator.


int a = 10;
int* ptr = &a;

printf("%d", *ptr); // With *ptr I'm dereferencing the pointer.
// Which means, I am asking the value pointed at by the pointer.
// ptr is pointing to the location in memory of the variable a.
// In a's location, we have 10. So, dereferencing gives this value.

// Since we have indirect control over a's location, we can modify its content using the pointer. This is an indirect way to access a.

*ptr = 20; // Now a's content is no longer 10, and has been modified to 20.





A pointer doesn't point to a value, it points to an object.
– Keith Thompson
Apr 30 '13 at 5:04





@KeithThompson A pointer does not point to an object, it points to a memory address, where an object (maybe a primitive) is located.
– mg30rg
Mar 6 '14 at 14:26





@mg30rg: I'm not sure what distinction you're making. A pointer value is an address. An object, by definition, is a "region of data storage in the execution environment, the contents of which can represent values". And what do you mean by "primitive"? The C standard doesn't use that term.
– Keith Thompson
Mar 6 '14 at 16:34





@KeithThompson I was barely pointing out, that you did not actually add value to the answer, you were only nitpicking on terminology (and did that wrong also). The pointer value surely is an address, that's how it "points" to a memory address. The word "object" in our OOPdriven world can be misleading, because it can be interpreted as "class instance" (yep, I was not aware that the question is labeled [C] and not [C++]), and I used the word "primitive" as in the opposite of "copmlex" (data structure like a struct or class).
– mg30rg
Mar 7 '14 at 8:26





Let me add to this answer that the array subscript operator also dereferences a pointer (a[b] is defined to mean *(a + b)).
– cmaster
Jun 16 '14 at 7:47



a[b]


*(a + b)



A pointer is a "reference" to a value.. much like a library call number is a reference to a book. "Dereferencing" the call number is physically going through and retrieving that book.


int a=4 ;
int *pA = &a ;
printf( "The REFERENCE/call number for the variable `a` is %pn", pA ) ;

// The * causes pA to DEREFERENCE... `a` via "callnumber" `pA`.
printf( "%dn", *pA ) ; // prints 4..



If the book isn't there, the librarian starts shouting, shuts the library down, and a couple of people are set to investigate the cause of a person going to find a book that isn't there.



In simple words, dereferencing means accessing the value from a certain memory location against which that pointer is pointing.



Code and explanation from Pointer Basics:



The dereference operation starts at
the pointer and follows its arrow over
to access its pointee. The goal may be
to look at the pointee state or to
change the pointee state. The
dereference operation on a pointer
only works if the pointer has a
pointee -- the pointee must be
allocated and the pointer must be set
to point to it. The most common error
in pointer code is forgetting to set
up the pointee. The most common
runtime crash because of that error in
the code is a failed dereference
operation. In Java the incorrect
dereference will be flagged politely
by the runtime system. In compiled
languages such as C, C++, and Pascal,
the incorrect dereference will
sometimes crash, and other times
corrupt memory in some subtle, random
way. Pointer bugs in compiled
languages can be difficult to track
down for this reason.


void main() {
int* x; // Allocate the pointer x
x = malloc(sizeof(int)); // Allocate an int pointee,
// and set x to point to it
*x = 42; // Dereference x to store 42 in its pointee
}





You actually have to allocate memory for where x is supposed to point at. Your example has undefined behavior.
– Peyman
Feb 10 '11 at 9:23





@Peyman That would be the malloc command.
– Dr Eval
Sep 8 '17 at 12:55



I think all the previous answers are wrong, as they
state that dereferencing means accessing the actual value.
Wikipedia gives the correct definition instead:
https://en.wikipedia.org/wiki/Dereference_operator



It operates on a pointer variable, and returns an l-value equivalent to the value at the pointer address. This is called "dereferencing" the pointer.



That said, we can dereference the pointer without ever
accessing the value it points to. For example:


char *p = NULL;
*p;



We dereferenced the NULL pointer without accessing its
value. Or we could do:


p1 = &(*p);
sz = sizeof(*p);



Again, dereferencing, but never accessing the value. Such code will NOT crash:
The crash happens when you actually access the data by an
invalid pointer. However, unfortunately, according the the
standard, dereferencing an invalid pointer is an undefined
behaviour (with a few exceptions), even if you don't try to
touch the actual data.



So in short: dereferencing the pointer means applying the
dereference operator to it. That operator just returns an
l-value for your future use.





well,you dereferenced a NULL pointer ,that would lead to segmentation fault.
– arjun gaur
Sep 2 '16 at 10:03





on top of that you searched for 'dereferencing operator' and not 'dereferencing a pointer' which actually means getting the value/accessing a value at a memory location being pointed to by a pointer.
– arjun gaur
Sep 2 '16 at 10:06





Have you tried? I did. The following does not crash: ` #include <stdlib.h> int main() { char *p = NULL; *p; return 0; } `
– stsp
Sep 3 '16 at 12:04






@stsp Does because the code doesn't crash now doesn't mean that it won't in future, or on some other system.
– Dr Eval
Sep 10 '17 at 15:50





The question was about what dereferencing the pointer means. Whether it can theoretically crash or not when you dereference the pointer w/o touching the actual memory location, is out of the question's scope. On any common arches and compilers this won't crash.
– stsp
Sep 11 '17 at 17:35





Thank you for your interest in this question.
Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).


Would you like to answer one of these unanswered questions instead?

ZEZ3j9k1
lxJKh0YDPUA56BLDbdfPpvE LT,69cq6DH4,oZOPJHMb3it0WplRGpNOZ NrXg9gGwElUVp0D0yDwcaJIiCroDIzOVNxufklbwfkKSi

Popular posts from this blog

PHP contact form sending but not receiving emails

Do graphics cards have individual ID by which single devices can be distinguished?

Create weekly swift ios local notifications