Pointer (computer programming)
This article needs additional citations for verification. (April 2018) |
I do consider assignment statements and pointer variables to be among computer science's "most valuable treasures."
Donald Knuth, Structured Programming, with go to Statements[1]
In
Using pointers significantly improves
structures). In particular, it is often much cheaper in time and space to copy and dereference pointers than it is to copy and access the data to which the pointers point.Pointers are also used to hold the addresses of entry points for
A pointer is a simple, more concrete implementation of the more abstract
History
In 1955, Soviet Ukrainian computer scientist
Formal description
In computer science, a pointer is a kind of reference.
A data primitive (or just primitive) is any datum that can be read from or written to computer memory using one memory access (for instance, both a byte and a word are primitives).
A data aggregate (or just aggregate) is a group of primitives that are
A pointer is a programming concept used in computer science to reference or point to a memory location that stores a value or an object. It is essentially a variable that stores the memory address of another variable or data structure rather than storing the data itself.
Pointers are commonly used in programming languages that support direct memory manipulation, such as C and C++. They allow programmers to work with memory directly, enabling efficient memory management and more complex data structures. By using pointers, you can access and modify data located in memory, pass data efficiently between functions, and create dynamic data structures like linked lists, trees, and graphs.
In simpler terms, you can think of a pointer as an arrow that points to a specific spot in a computer's memory, allowing you to interact with the data stored at that location.
A memory pointer (or just pointer) is a primitive, the value of which is intended to be used as a memory address; it is said that a pointer points to a memory address. It is also said that a pointer points to a datum [in memory] when the pointer's value is the datum's memory address.
More generally, a pointer is a kind of reference, and it is said that a pointer references a datum stored somewhere in memory; to obtain that datum is to dereference the pointer. The feature that separates pointers from other kinds of reference is that a pointer's value is meant to be interpreted as a memory address, which is a rather low-level concept.
References serve as a level of indirection: A pointer's value determines which memory address (that is, which datum) is to be used in a calculation. Because indirection is a fundamental aspect of algorithms, pointers are often expressed as a fundamental
of a pointer determines the type of the datum to which the pointer points.Architectural roots
Pointers are a very thin
In the usual case, a pointer is large enough to hold more addresses than there are units of memory in the system. This introduces the possibility that a program may attempt to access an address which corresponds to no unit of memory, either because not enough memory is installed (i.e. beyond the range of available memory) or the architecture does not support such addresses. The first case may, in certain platforms such as the Intel x86 architecture, be called a segmentation fault (segfault). The second case is possible in the current implementation of AMD64, where pointers are 64 bit long and addresses only extend to 48 bits. Pointers must conform to certain rules (canonical addresses), so if a non-canonical pointer is dereferenced, the processor raises a general protection fault.
On the other hand, some systems have more units of memory than there are addresses. In this case, a more complex scheme such as
In order to provide a consistent interface, some architectures provide
Uses
Pointers are directly supported without restrictions in languages such as
In functional programming languages that rely heavily on lists, data references are managed abstractly by using primitive constructs like
When dealing with arrays, the critical lookup operation typically involves a stage called address calculation which involves constructing a pointer to the desired data element in the array. In other data structures, such as linked lists, pointers are used as references to explicitly tie one piece of the structure to another.
Pointers are used to pass parameters by reference. This is useful if the programmer wants a function's modifications to a parameter to be visible to the function's caller. This is also useful for returning multiple values from a function.
Pointers can also be used to
C pointers
The basic syntax to define a pointer is:[4]
int *ptr;
This declares ptr
as the identifier of an object of the following type:
- pointer that points to an object of type
int
This is usually stated more succinctly as "ptr
is a pointer to int
."
Because the C language does not specify an implicit initialization for objects of automatic storage duration,[5] care should often be taken to ensure that the address to which ptr
points is valid; this is why it is sometimes suggested that a pointer be explicitly initialized to the null pointer value, which is traditionally specified in C with the standardized macro NULL
:[6]
int *ptr = NULL;
Dereferencing a null pointer in C produces undefined behavior,[7] which could be catastrophic. However, most implementations[citation needed] simply halt execution of the program in question, usually with a segmentation fault.
However, initializing pointers unnecessarily could hinder program analysis, thereby hiding bugs.
In any case, once a pointer has been declared, the next logical step is for it to point at something:
int a = 5;
int *ptr = NULL;
ptr = &a;
This assigns the value of the address of a
to ptr
. For example, if a
is stored at memory location of 0x8130 then the value of ptr
will be 0x8130 after the assignment. To dereference the pointer, an asterisk is used again:
*ptr = 8;
This means take the contents of ptr
(which is 0x8130), "locate" that address in memory and set its value to 8.
If a
is later accessed again, its new value will be 8.
This example may be clearer if memory is examined directly.
Assume that a
is located at address 0x8130 in memory and ptr
at 0x8134; also assume this is a 32-bit machine such that an int is 32-bits wide. The following is what would be in memory after the following code snippet is executed:
int a = 5;
int *ptr = NULL;
Address | Contents |
---|---|
0x8130 | 0x00000005 |
0x8134 | 0x00000000 |
(The NULL pointer shown here is 0x00000000.)
By assigning the address of a
to ptr
:
ptr = &a;
yields the following memory values:
Address | Contents |
---|---|
0x8130 | 0x00000005 |
0x8134 | 0x00008130 |
Then by dereferencing ptr
by coding:
*ptr = 8;
the computer will take the contents of ptr
(which is 0x8130), 'locate' that address, and assign 8 to that location yielding the following memory:
Address | Contents |
---|---|
0x8130 | 0x00000008 |
0x8134 | 0x00008130 |
Clearly, accessing a
will yield the value of 8 because the previous instruction modified the contents of a
by way of the pointer ptr
.
Use in data structures
When setting up
Relative addresses are a form of manual
A one byte offset, such as the hexadecimal
C arrays
In C, array indexing is formally defined in terms of pointer arithmetic; that is, the language specification requires that array[i]
be equivalent to *(array + i)
.[8] Thus in C, arrays can be thought of as pointers to consecutive areas of memory (with no gaps),[8] and the syntax for accessing arrays is identical for that which can be used to dereference pointers. For example, an array array
can be declared and used in the following manner:
int array[5]; /* Declares 5 contiguous integers */
int *ptr = array; /* Arrays can be used as pointers */
ptr[0] = 1; /* Pointers can be indexed with array syntax */
*(array + 1) = 2; /* Arrays can be dereferenced with pointer syntax */
*(1 + array) = 2; /* Pointer addition is commutative */
2[array] = 4; /* Subscript operator is commutative */
This allocates a block of five integers and names the block array
, which acts as a pointer to the block. Another common use of pointers is to point to dynamically allocated memory from
While most operators on arrays and pointers are equivalent, the result of the sizeof
operator differs. In this example, sizeof(array)
will evaluate to 5*sizeof(int)
(the size of the array), while sizeof(ptr)
will evaluate to sizeof(int*)
, the size of the pointer itself.
Default values of an array can be declared like:
int array[5] = {2, 4, 3, 1, 5};
If array
is located in memory starting at address 0x1000 on a 32-bit little-endian machine then memory will contain the following (values are in hexadecimal, like the addresses):
0 1 2 3 1000 2 0 0 0 1004 4 0 0 0 1008 3 0 0 0 100C 1 0 0 0 1010 5 0 0 0
Represented here are five integers: 2, 4, 3, 1, and 5. These five integers occupy 32 bits (4 bytes) each with the least-significant byte stored first (this is a little-endian
The syntax for C with pointers is:
array
means 0x1000;array + 1
means 0x1004: the "+ 1" means to add the size of 1int
, which is 4 bytes;*array
means to dereference the contents ofarray
. Considering the contents as a memory address (0x1000), look up the value at that location (0x0002);array[i]
means element numberi
, 0-based, ofarray
which is translated into*(array + i)
.
The last example is how to access the contents of array
. Breaking it down:
array + i
is the memory location of the (i)th element ofarray
, starting at i=0;*(array + i)
takes that memory address and dereferences it to access the value.
C linked list
Below is an example definition of a linked list in C.
/* the empty linked list is represented by NULL
* or some other sentinel value */
#define EMPTY_LIST NULL
struct link {
void *data; /* data of this link */
struct link *next; /* next link; EMPTY_LIST if there is none */
};
This pointer-recursive definition is essentially the same as the reference-recursive definition from the
data Link a = Nil
| Cons a (Link a)
Nil
is the empty list, and Cons a (Link a)
is a cons cell of type a
with another link also of type a
.
The definition with references, however, is type-checked and does not use potentially confusing signal values. For this reason, data structures in C are usually dealt with via wrapper functions, which are carefully checked for correctness.
Pass-by-address using pointers
Pointers can be used to pass variables by their address, allowing their value to be changed. For example, consider the following C code:
/* a copy of the int n can be changed within the function without affecting the calling code */
void passByValue(int n) {
n = 12;
}
/* a pointer m is passed instead. No copy of the value pointed to by m is created */
void passByAddress(int *m) {
*m = 14;
}
int main(void) {
int x = 3;
/* pass a copy of x's value as the argument */
passByValue(x);
// the value was changed inside the function, but x is still 3 from here on
/* pass x's address as the argument */
passByAddress(&x);
// x was actually changed by the function and is now equal to 14 here
return 0;
}
Dynamic memory allocation
In some programs, the required amount of memory depends on what the user may enter. In such cases the programmer needs to allocate memory dynamically. This is done by allocating memory at the heap rather than on the stack, where variables usually are stored (although variables can also be stored in the CPU registers). Dynamic memory allocation can only be made through pointers, and names – like with common variables – cannot be given.
Pointers are used to store and manage the addresses of
The example C code below illustrates how structure objects are dynamically allocated and referenced. The
malloc()
/* Parts inventory item */
struct Item {
int id; /* Part number */
char * name; /* Part name */
float cost; /* Cost */
};
/* Allocate and initialize a new Item object */
struct Item * make_item(const char *name) {
struct Item * item;
/* Allocate a block of memory for a new Item object */
item = malloc(sizeof(struct Item));
if (item == NULL)
return NULL;
/* Initialize the members of the new Item */
memset(item, 0, sizeof(struct Item));
item->id = -1;
item->name = NULL;
item->cost = 0.0;
/* Save a copy of the name in the new Item */
item->name = malloc(strlen(name) + 1);
if (item->name == NULL) {
free(item);
return NULL;
}
strcpy(item->name, name);
/* Return the newly created Item object */
return item;
}
The code below illustrates how memory objects are dynamically deallocated, i.e., returned to the heap or free store. The standard C library provides the function
free()
/* Deallocate an Item object */
void destroy_item(struct Item *item) {
/* Check for a null object pointer */
if (item == NULL)
return;
/* Deallocate the name string saved within the Item */
if (item->name != NULL) {
free(item->name);
item->name = NULL;
}
/* Deallocate the Item object itself */
free(item);
}
Memory-mapped hardware
On some computing architectures, pointers can be used to directly manipulate memory or memory-mapped devices.
Assigning addresses to pointers is an invaluable tool when programming microcontrollers. Below is a simple example declaring a pointer of type int and initialising it to a hexadecimal address in this example the constant 0x7FFF:
int *hardware_address = (int *)0x7FFF;
In the mid 80s, using the BIOS to access the video capabilities of PCs was slow. Applications that were display-intensive typically used to access CGA video memory directly by casting the hexadecimal constant 0xB8000 to a pointer to an array of 80 unsigned 16-bit int values. Each value consisted of an ASCII code in the low byte, and a colour in the high byte. Thus, to put the letter 'A' at row 5, column 2 in bright white on blue, one would write code like the following:
#define VID ((unsigned short (*)[80])0xB8000)
void foo(void) {
VID[4][1] = 0x1F00 | 'A';
}
Use in control tables
Typed pointers and casting
In many languages, pointers have the additional restriction that the object they point to has a specific
For example, in C
int *money;
char *bags;
money
would be an integer pointer and bags
would be a char pointer.
The following would yield a compiler warning of "assignment from incompatible pointer type" under GCC
bags = money;
because money
and bags
were declared with different types.
To suppress the compiler warning, it must be made explicit that you do indeed wish to make the assignment by typecasting it
bags = (char *)money;
which says to cast the integer pointer of money
to a char pointer and assign to bags
.
A 2005 draft of the C standard requires that casting a pointer derived from one type to one of another type should maintain the alignment correctness for both types (6.3.2.3 Pointers, par. 7):[9]
char *external_buffer = "abcdef";
int *internal_data;
internal_data = (int *)external_buffer; // UNDEFINED BEHAVIOUR if "the resulting pointer
// is not correctly aligned"
In languages that allow pointer arithmetic, arithmetic on pointers takes into account the size of the type. For example, adding an integer number to a pointer produces another pointer that points to an address that is higher by that number times the size of the type. This allows us to easily compute the address of elements of an array of a given type, as was shown in the C arrays example above. When a pointer of one type is cast to another type of a different size, the programmer should expect that pointer arithmetic will be calculated differently. In C, for example, if the money
array starts at 0x2000 and sizeof(int)
is 4 bytes whereas sizeof(char)
is 1 byte, then money + 1
will point to 0x2004, but bags + 1
would point to 0x2001. Other risks of casting include loss of data when "wide" data is written to "narrow" locations (e.g. bags[0] = 65537;
), unexpected results when
Although it is impossible in general to determine at compile-time which casts are safe, some languages store run-time type information which can be used to confirm that these dangerous casts are valid at runtime. Other languages merely accept a conservative approximation of safe casts, or none at all.
Value of pointers
In C and C++, even if two pointers compare as equal that doesn't mean they are equivalent. In these languages and LLVM, the rule is interpreted to mean that "just because two pointers point to the same address, does not mean they are equal in the sense that they can be used interchangeably", the difference between the pointers referred to as their provenance.[10] Casting to an integer type such as uintptr_t
is implementation-defined and the comparison it provides does not provide any more insight as to whether the two pointers are interchangeable. In addition, further conversion to bytes and arithmetic will throw off optimizers trying to keep track the use of pointers, a problem still being elucidated in academic research.[11]
Making pointers safer
As a pointer allows a program to attempt to access an object that may not be defined, pointers can be the origin of a variety of programming errors. However, the usefulness of pointers is so great that it can be difficult to perform programming tasks without them. Consequently, many languages have created constructs designed to provide some of the useful features of pointers without some of their pitfalls, also sometimes referred to as pointer hazards. In this context, pointers that directly address memory (as used in this article) are referred to as raw pointers, by contrast with smart pointers or other variants.
One major problem with pointers is that as long as they can be directly manipulated as a number, they can be made to point to unused addresses or to data which is being used for other purposes. Many languages, including most
A pointer which does not have any address assigned to it is called a
In systems with explicit memory allocation, it is possible to create a dangling pointer by deallocating the memory region it points into. This type of pointer is dangerous and subtle because a deallocated memory region may contain the same data as it did before it was deallocated but may be then reallocated and overwritten by unrelated code, unknown to the earlier code. Languages with garbage collection prevent this type of error because deallocation is performed automatically when there are no more references in scope.
Some languages, like
The
Special kinds of pointers
Kinds defined by value
Null pointer
A null pointer has a value reserved for indicating that the pointer does not refer to a valid object. Null pointers are routinely used to represent conditions such as the end of a
Dangling pointer
A dangling pointer is a pointer that does not point to a valid object and consequently may make a program crash or behave oddly. In the Pascal or C programming languages, pointers that are not specifically initialized may point to unpredictable addresses in memory.
The following example code shows a dangling pointer:
int func(void) {
char *p1 = malloc(sizeof(char)); /* (undefined) value of some place on the heap */
char *p2; /* dangling (uninitialized) pointer */
*p1 = 'a'; /* This is OK, assuming malloc() has not returned NULL. */
*p2 = 'b'; /* This invokes undefined behavior */
}
Here, p2
may point to anywhere in memory, so performing the assignment *p2 = 'b';
can corrupt an unknown area of memory or trigger a segmentation fault.
Wild branch
Where a pointer is used as the address of the entry point to a program or start of a
The consequences are usually unpredictable and the error may present itself in several different ways depending upon whether or not the pointer is a "valid" address and whether or not there is (coincidentally) a valid instruction (opcode) at that address. The detection of a wild branch can present one of the most difficult and frustrating debugging exercises since much of the evidence may already have been destroyed beforehand or by execution of one or more inappropriate instructions at the branch location. If available, an instruction set simulator can usually not only detect a wild branch before it takes effect, but also provide a complete or partial trace of its history.
Kinds defined by structure
Autorelative pointer
An autorelative pointer is a pointer whose value is interpreted as an offset from the address of the pointer itself; thus, if a data structure has an autorelative pointer member that points to some portion of the data structure itself, then the data structure may be relocated in memory without having to update the value of the auto relative pointer.[12]
The cited patent also uses the term self-relative pointer to mean the same thing. However, the meaning of that term has been used in other ways:
- to mean an offset from the address of a structure rather than from the address of the pointer itself;[citation needed]
- to mean a pointer containing its own address, which can be useful for reconstructing in any arbitrary region of memory a collection of data structures that point to each other.[13]
Based pointer
A based pointer is a pointer whose value is an offset from the value of another pointer. This can be used to store and load blocks of data, assigning the address of the beginning of the block to the base pointer.[14]
Kinds defined by use or datatype
Multiple indirection
In some languages, a pointer can reference another pointer, requiring multiple dereference operations to get to the original value. While each level of indirection may add a performance cost, it is sometimes necessary in order to provide correct behavior for complex
struct element {
struct element *next;
int value;
};
struct element *head = NULL;
This implementation uses a pointer to the first element in the list as a surrogate for the entire list. If a new value is added to the beginning of the list, head
has to be changed to point to the new element. Since C arguments are always passed by value, using double indirection allows the insertion to be implemented correctly, and has the desirable side-effect of eliminating special case code to deal with insertions at the front of the list:
// Given a sorted list at *head, insert the element item at the first
// location where all earlier elements have lesser or equal value.
void insert(struct element **head, struct element *item) {
struct element **p; // p points to a pointer to an element
for (p = head; *p != NULL; p = &(*p)->next) {
if (item->value <= (*p)->value)
break;
}
item->next = *p;
*p = item;
}
// Caller does this:
insert(&head, item);
In this case, if the value of item
is less than that of head
, the caller's head
is properly updated to the address of the new item.
A basic example is in the
char **argv
—this is because the variable argv
itself is a pointer to an array of strings (an array of arrays), so *argv
is a pointer to the 0th string (by convention the name of the program), and **argv
is the 0th character of the 0th string.
Function pointer
In some languages, a pointer can reference executable code, i.e., it can point to a function, method, or procedure. A function pointer will store the address of a function to be invoked. While this facility can be used to call functions dynamically, it is often a favorite technique of virus and other malicious software writers.
int sum(int n1, int n2) { // Function with two integer parameters returning an integer value
return n1 + n2;
}
int main(void) {
int a, b, x, y;
int (*fp)(int, int); // Function pointer which can point to a function like sum
fp = ∑ // fp now points to function sum
x = (*fp)(a, b); // Calls function sum with arguments a and b
y = sum(a, b); // Calls function sum with arguments a and b
}
Back pointer
In doubly linked lists or tree structures, a back pointer held on an element 'points back' to the item referring to the current element. These are useful for navigation and manipulation, at the expense of greater memory use.
Simulation using an array index
It is possible to simulate pointer behavior using an index to an (normally one-dimensional) array.
Primarily for languages which do not support pointers explicitly but do support arrays, the
It is even theoretically possible, using the above technique, together with a suitable
Support in various programming languages
Ada
System.Storage_Elements
.
BASIC
Several old versions of BASIC for the Windows platform had support for STRPTR() to return the address of a string, and for VARPTR() to return the address of a variable. Visual Basic 5 also had support for OBJPTR() to return the address of an object interface, and for an ADDRESSOF operator to return the address of a function. The types of all of these are integers, but their values are equivalent to those held by pointer types.
Newer dialects of
ANY
pointers (equivalent to C's void*
) are treated as though the ANY
pointer was a byte width. ANY
pointers cannot be dereferenced, as in C. Also, casting between ANY
and any other type's pointers will not generate any warnings.
dim as integer f = 257
dim as any ptr g = @f
dim as integer ptr i = g
assert(*i = 257)
assert( (g + 4) = (@f + 1) )
C and C++
In C and C++ pointers are variables that store addresses and can be null. Each pointer has a type it points to, but one can freely cast between pointer types (but not between a function pointer and an object pointer). A special pointer type called the “void pointer” allows pointing to any (non-function) object, but is limited by the fact that it cannot be dereferenced directly (it shall be cast). The address itself can often be directly manipulated by casting a pointer to and from an integral type of sufficient size, though the results are implementation-defined and may indeed cause undefined behavior; while earlier C standards did not have an integral type that was guaranteed to be large enough, C99 specifies the uintptr_t
typedef name defined in <stdint.h>
, but an implementation need not provide it.
C++ fully supports C pointers and C typecasting. It also supports a new group of typecasting operators to help catch some unintended dangerous casts at compile-time. Since C++11, the C++ standard library also provides smart pointers (unique_ptr
, shared_ptr
and weak_ptr
) which can be used in some situations as a safer alternative to primitive C pointers. C++ also supports another form of reference, quite different from a pointer, called simply a reference or reference type.
Pointer arithmetic, that is, the ability to modify a pointer's target address with arithmetic operations (as well as magnitude comparisons), is restricted by the language standard to remain within the bounds of a single array object (or just after it), and will otherwise invoke
void
pointers because the void type has no size, and thus the pointed address can not be added to, although gccvoid*
as a non-standard extension, treating it as if it were char *
.
Pointer arithmetic provides the programmer with a single way of dealing with different types: adding and subtracting the number of elements required instead of the actual offset in bytes. (Pointer arithmetic with char *
pointers uses byte offsets, because sizeof(char)
is 1 by definition.) In particular, the C definition explicitly declares that the syntax a[n]
, which is the n
-th element of the array a
, is equivalent to *(a + n)
, which is the content of the element pointed by a + n
. This implies that n[a]
is equivalent to a[n]
, and one can write, e.g., a[3]
or 3[a]
equally well to access the fourth element of an array a
.
While powerful, pointer arithmetic can be a source of
The void
pointer, or void*
, is supported in ANSI C and C++ as a generic pointer type. A pointer to void
can store the address of any object (not function),[a] and, in C, is implicitly converted to any other object pointer type on assignment, but it must be explicitly cast if dereferenced.
K&R C used char*
for the “type-agnostic pointer” purpose (before ANSI C).
int x = 4;
void* p1 = &x;
int* p2 = p1; // void* implicitly converted to int*: valid C, but not C++
int a = *p2;
int b = *(int*)p1; // when dereferencing inline, there is no implicit conversion
C++ does not allow the implicit conversion of void*
to other pointer types, even in assignments. This was a design decision to avoid careless and even unintended casts, though most compilers only output warnings, not errors, when encountering other casts.
int x = 4;
void* p1 = &x;
int* p2 = p1; // this fails in C++: there is no implicit conversion from void*
int* p3 = (int*)p1; // C-style cast
int* p4 = reinterpret_cast<int*>(p1); // C++ cast
In C++, there is no void&
(reference to void) to complement void*
(pointer to void), because references behave like aliases to the variables they point to, and there can never be a variable whose type is void
.
Pointer-to-member
In C++ pointers to non-static members of a class can be defined. If a class C
has a member T a
then &C::a
is a pointer to the member a
of type T C::*
. This member can be an object or a function.[16] They can be used on the right-hand side of operators .*
and ->*
to access the corresponding member.
struct S {
int a;
int f() const {return a;}
};
S s1{};
S* ptrS = &s1;
int S::* ptr = &S::a; // pointer to S::a
int (S::* fp)()const = &S::f; // pointer to S::f
s1.*ptr = 1;
std::cout << (s1.*fp)() << "\n"; // prints 1
ptrS->*ptr = 2;
std::cout << (ptrS->*fp)() << "\n"; // prints 2
Pointer declaration syntax overview
These pointer declarations cover most variants of pointer declarations. Of course it is possible to have triple pointers, but the main principles behind a triple pointer already exist in a double pointer. The naming used here is what the expression typeid(type).name()
equals for each of these types when using
char A5_A5_c [5][5]; /* array of arrays of chars */
char *A5_Pc [5]; /* array of pointers to chars */
char **PPc; /* pointer to pointer to char ("double pointer") */
char (*PA5_c) [5]; /* pointer to array(s) of chars */
char *FPcvE(); /* function which returns a pointer to char(s) */
char (*PFcvE)(); /* pointer to a function which returns a char */
char (*FPA5_cvE())[5]; /* function which returns pointer to an array of chars */
char (*A5_PFcvE[5])(); /* an array of pointers to functions which return a char */
The following declarations involving pointers-to-member are valid only in C++:
class C;
class D;
char C::* M1Cc; /* pointer-to-member to char */
char C::*A5_M1Cc [5]; /* array of pointers-to-member to char */
char* C::* M1CPc; /* pointer-to-member to pointer to char(s) */
char C::** PM1Cc; /* pointer to pointer-to-member to char */
char (*M1CA5_c) [5]; /* pointer-to-member to array(s) of chars */
char C::* FM1CcvE(); /* function which returns a pointer-to-member to char */
char D::* C::* M1CM1Dc; /* pointer-to-member to pointer-to-member to pointer to char(s) */
char C::* C::* M1CMS_c; /* pointer-to-member to pointer-to-member to pointer to char(s) */
char (C::* FM1CA5_cvE())[5]; /* function which returns pointer-to-member to an array of chars */
char (C::* M1CFcvE)() /* pointer-to-member-function which returns a char */
char (C::* A5_M1CFcvE[5])(); /* an array of pointers-to-member-functions which return a char */
The ()
and []
have a higher priority than *
.
[19]
C#
In the C# programming language, pointers are supported by either marking blocks of code that include pointers with the unsafe
keyword, or by using
the System.Runtime.CompilerServices
assembly provisions for pointer access.
The syntax is essentially the same as in C++, and the address pointed can be either managed or unmanaged memory. However, pointers to managed memory (any pointer to a managed object) must be declared using the fixed
keyword, which prevents the garbage collector from moving the pointed object as part of memory management while the pointer is in scope, thus keeping the pointer address valid.
However, an exception to this is from using the IntPtr
structure, which is a memory managed equivalent to int*
, and does not require the unsafe
keyword nor the CompilerServices
assembly. This type is often returned when using methods from the System.Runtime.InteropServices
, for example:
// Get 16 bytes of memory from the process's unmanaged memory
IntPtr pointer = System.Runtime.InteropServices.Marshal.AllocHGlobal(16);
// Do something with the allocated memory
// Free the allocated memory
System.Runtime.InteropServices.Marshal.FreeHGlobal(pointer);
The .NET framework includes many classes and methods in the System
and System.Runtime.InteropServices
namespaces (such as the Marshal
class) which convert .NET types (for example, System.String
) to and from many unmanaged types and pointers (for example, LPWSTR
or void*
) to allow communication with unmanaged code. Most such methods have the same security permission requirements as unmanaged code, since they can affect arbitrary places in memory.
COBOL
The COBOL programming language supports pointers to variables. Primitive or group (record) data objects declared within the LINKAGE SECTION
of a program are inherently pointer-based, where the only memory allocated within the program is space for the address of the data item (typically a single memory word). In program source code, these data items are used just like any other WORKING-STORAGE
variable, but their contents are implicitly accessed indirectly through their LINKAGE
pointers.
Memory space for each pointed-to data object is typically
EXEC CICS
or EXEC SQL
Extended versions of COBOL also provide pointer variables declared with USAGE
IS
POINTER
clauses. The values of such pointer variables are established and modified using SET
and SET
ADDRESS
statements.
Some extended versions of COBOL also provide PROCEDURE-POINTER
variables, which are capable of storing the addresses of executable code.
PL/I
The
DECLARE xxx POINTER;
, which declares a pointer named "xxx". Pointers are used with BASED
variables. A based variable can be declared with a default locator (DECLARE xxx BASED(ppp);
or without (DECLARE xxx BASED;
), where xxx is a based variable, which may be an element variable, a structure, or an array, and ppp is the default pointer). Such a variable can be address without an explicit pointer reference (xxx=1;
, or may be addressed with an explicit reference to the default locator (ppp), or to any other pointer (qqq->xxx=1;
).
Pointer arithmetic is not part of the PL/I standard, but many compilers allow expressions of the form ptr = ptr±expression
. IBM PL/I also has the builtin function PTRADD
to perform the arithmetic. Pointer arithmetic is always performed in bytes.
IBM Enterprise PL/I compilers have a new form of typed pointer called a HANDLE
.
D
The D programming language is a derivative of C and C++ which fully supports C pointers and C typecasting.
Eiffel
The Eiffel object-oriented language employs value and reference semantics without pointer arithmetic. Nevertheless, pointer classes are provided. They offer pointer arithmetic, typecasting, explicit memory management, interfacing with non-Eiffel software, and other features.
Fortran
Fortran-90 introduced a strongly typed pointer capability. Fortran pointers contain more than just a simple memory address. They also encapsulate the lower and upper bounds of array dimensions, strides (for example, to support arbitrary array sections), and other metadata. An association operator, =>
is used to associate a POINTER
to a variable which has a TARGET
attribute. The Fortran-90 ALLOCATE
statement may also be used to associate a pointer to a block of memory. For example, the following code might be used to define and create a linked list structure:
type real_list_t
real :: sample_data(100)
type (real_list_t), pointer :: next => null ()
end type
type (real_list_t), target :: my_real_list
type (real_list_t), pointer :: real_list_temp
real_list_temp => my_real_list
do
read (1,iostat=ioerr) real_list_temp%sample_data
if (ioerr /= 0) exit
allocate (real_list_temp%next)
real_list_temp => real_list_temp%next
end do
Fortran-2003 adds support for procedure pointers. Also, as part of the C Interoperability feature, Fortran-2003 supports intrinsic functions for converting C-style pointers into Fortran pointers and back.
Go
Go has pointers. Its declaration syntax is equivalent to that of C, but written the other way around, ending with the type. Unlike C, Go has garbage collection, and disallows pointer arithmetic. Reference types, like in C++, do not exist. Some built-in types, like maps and channels, are boxed (i.e. internally they are pointers to mutable structures), and are initialized using the make
function. In an approach to unified syntax between pointers and non-pointers, the arrow (->
) operator has been dropped: the dot operator on a pointer refers to the field or method of the dereferenced object. This, however, only works with 1 level of indirection.
Java
There is no explicit representation of pointers in
Modula-2
Pointers are implemented very much as in Pascal, as are VAR
parameters in procedure calls. Modula-2 is even more strongly typed than Pascal, with fewer ways to escape the type system. Some of the variants of Modula-2 (such as Modula-3) include garbage collection.
Oberon
Much as with Modula-2, pointers are available. There are still fewer ways to evade the type system and so Oberon and its variants are still safer with respect to pointers than Modula-2 or its variants. As with Modula-3, garbage collection is a part of the language specification.
Pascal
Unlike many languages that feature pointers, standard
However, in some commercial and open source Pascal (or derivatives) compiler implementations —like
Inc
or Dec
standard procedures with it moves the pointer by the size of the data typePointer
, which is compatible with other pointer types.
Perl
The Perl programming language supports pointers, although rarely used, in the form of the pack and unpack functions. These are intended only for simple interactions with compiled OS libraries. In all other cases, Perl uses references, which are typed and do not allow any form of pointer arithmetic. They are used to construct complex data structures.[24]
See also
Notes
References
- S2CID 207630080. Archived from the original(PDF) on August 24, 2009.
- ISBN 9781573565219. Retrieved 2018-04-13.
Harold Lawson pointer.
- ^ "IEEE Computer Society awards list". Awards.computer.org. Archived from the original on 2011-03-22. Retrieved 2018-04-13.
- ^ ISO/IEC 9899, clause 6.7.5.1, paragraph 1.
- ^ ISO/IEC 9899, clause 6.7.8, paragraph 10.
- ^ ISO/IEC 9899, clause 7.17, paragraph 3: NULL... which expands to an implementation-defined null pointer constant...
- ^ ISO/IEC 9899, clause 6.5.3.2, paragraph 4, footnote 87: If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined... Among the invalid values for dereferencing a pointer by the unary * operator are a null pointer...
- ^ ISBN 978-1-55615-359-4.
An array type does not contain additional holes because all other types pack tightly when composed into arrays [at page 51]
- ^ WG14 N1124, C – Approved standards: ISO/IEC 9899 – Programming languages – C, 2005-05-06.
- ^ Jung, Ralf. "Pointers Are Complicated II, or: We need better language specs".
- ^ Jung, Ralf. "Pointers Are Complicated, or: What's in a Byte?".
- ^ us patent 6625718, Steiner, Robert C. (Broomfield, CO), "Pointers that are relative to their own present locations", issued 2003-09-23, assigned to Avaya Technology Corp. (Basking Ridge, NJ)
- ^ us patent 6115721, Nagy, Michael (Tampa, FL), "System and method for database save and restore using self-pointers", issued 2000-09-05, assigned to IBM (Armonk, NY)
- ^ "Based Pointers". Msdn.microsoft.com. Retrieved 2018-04-13.
- ^ "CWG Issue 195". cplusplus.github.io. Retrieved 2024-02-15.
- ^ "Pointers to Member Functions". isocpp.org. Retrieved 2022-11-26.
- ^ "c++filt(1) - Linux man page".
- ^ "Itanium C++ ABI".
- ISBN 91-44-01468-6
- ^ Nick Parlante, [1], Stanford Computer Science Education Library, pp. 9–10 (2000).
- ^ ISO 7185 Pascal Standard (unofficial copy), section 6.4.4 Pointer-types Archived 2017-04-24 at the Wayback Machine and subsequent.
- ^ J. Welsh, W. J. Sneeringer, and C. A. R. Hoare, "Ambiguities and Insecurities in Pascal," Software: Practice and Experience 7, pp. 685–696 (1977)
- ^ Free Pascal Language Reference guide, section 3.4 Pointers
- ^ Contact details. "// Making References (Perl References and nested data structures)". Perldoc.perl.org. Retrieved 2018-04-13.
External links
- PL/I List Processing Paper from the June, 1967 issue of CACM
- cdecl.org A tool to convert pointer declarations to plain English
- Over IQ.com A beginner level guide describing pointers in a plain English.
- Pointers and Memory Introduction to pointers – Stanford Computer Science Education Library
- Pointers in C programming Archived 2019-06-09 at the Wayback Machine A visual model for the beginners in C programming
- 0pointer.de A terse list of minimum length source codes that dereference a null pointer in several different programming languages
- "The C book" – containing pointer examples in ANSI C
- Joint Technical Committee ISO/IEC JTC 1, Subcommittee SC 22, Working Group WG 14 (2007-09-08). International Standard ISO/IEC 9899 (PDF).
{{cite book}}
:|work=
ignored (help)CS1 maint: multiple names: authors list (link) CS1 maint: numeric names: authors list (link).