recognize pointers
The content comes from "In-depth understanding of C pointers"
Declaring a pointer Follow
the data type with an asterisk *
, the following declarations are equivalent
int* pi;
int * pi;
int *pi;
int*pi;
Read the statement
below:
const int *pci;
1.
pci
is a variable const int *pci
;
2.pci
is a pointer variable const int*pci
;
3.pci
is a pointer variable const to an integerint *pci
;
4.pci
is a pointer variable to an integer constantconst int *pci
;
Address operator
The address operator &
returns the address of the operand
int num;
int *pi = #
print the value of the pointer
int num = 0;
int *pi = #
printf("Address of num: %p Value: %d\n", &num, num);
printf("Address of pi: %p Value: %p\n", &pi, pi);
The output might look like this:
Address of num: 0x7ffeefbff51c Value: 0
Address of pi: 0x7ffeefbff510 Value: 0x7ffeefbff51c
It is difficult to display pointer values in a consistent way across different platforms. One way is to convert the pointer to void
a pointer and then use %p
the format specifier to display:
printf("Value of pi: %p\n", (void *)pi);
Indirect reference operator
The indirect reference operator ( *
) returns the value pointed to by the pointer variable
NULL
NULL
being assigned to a pointer means that the pointer does not point to anything
NULL
Macros are void
integer constants that are cast to pointers 0
, and are defined in many libraries as follows:
#define NULL ((void *)0)
Tests whether the pointer is set to NULL
. If pi
assigned NULL
a value, it will be interpreted as binary0
pi = NULL;
if (pi) {
printf("pi is null\n");
} else {
printf("pi is not null\n");
}
or
if (pi == NULL) {
}
if (pi != NULL) {
}
void pointer
void
A pointer is a generic pointer used to store references of any data type
void *pv;
Any pointer can be assigned to void
a pointer, it can be converted back to the original pointer type, the value of the pointer is equal to the value of the original pointer
int num = 100;
int *pi = #
printf("Value of pi: %p\n", pi);
void *pv = pi;
pi = (int *)pv;
printf("Value of pi: %p\n", pi);
The output is as follows, showing that the pointer addresses are the same:
Value of pi: 0x7ffeefbff51c
Value of pi: 0x7ffeefbff51c
void
Pointers can only be used as data pointers, not function pointers
sizeof
operator can be used on void
pointers
size_t size = sizeof(void *);
size_t
Is the data type used to represent the length
Global and Static Pointers
Pointers declared as global or static are initialized at program startup asNULL
int *globalpi;
void foo() {
static int *staticpi;
}
int main(int argc, const char * argv[]) {
return 0;
}
size_t
size_t
The type represents the maximum length any object in C can be. It is an unsigned integer type, and negative numbers have no meaning here . It is
size_t
used as sizeof
the return value type of the operator, and it is also the parameter type of many functions. For example, the typical definition of malloc
and is as follows:strlen
size_t
size_t
The recommended format specifiers are%zu
size_t sizet = 5;
printf("%d\n", sizet);
printf("%zu\n", sizet);
sizeof
operator can be used to determine the length of the pointer
printf("Size of *char: %d\n", sizeof(char *));
intptr_t和uintptr_t
intptr_t
And uintptr_t
the address used to store the pointer.
They provide a portable and safe way to declare pointers, and are of the same size as pointers used in the system, useful for converting pointers to integer form are
uintptr_t
unsigned intptr_t
versions
pointer operation
add integer to pointer
Adding an integer to the pointer actually adds the number that is the product of the integer and the number of bytes corresponding to the pointer data type
int vector[] = {
28, 41, 7};
int *pi = vector;
printf("%d\n", *pi); //28
pi += 1;
printf("%d\n", *pi); //41
pi += 1;
printf("%d\n", *pi); //7
The array name here vector
is the address of the array and the address of the first element of the array
Subtract integer from pointer
Similar to addition, when subtracting an integer, the address value will be subtracted from the product of the length of the data type and the integer value
int vector[] = {
28, 41, 7};
int *pi = vector + 2;
printf("%d\n", *pi); //7
pi -= 1;
printf("%d\n", *pi); //41
pi -= 1;
printf("%d\n", *pi); //28
pointer subtraction
The difference between pointer subtraction is usually useless, but it can determine the order of elements in the array
ptrdiff_t
Portable way for types to represent pointer deltas
Common uses of pointers
multiple levels of indirection
Declare a variable as a pointer to a pointer, sometimes called a double pointer
#include <stdio.h>
int main(int argc, const char * argv[]) {
char *titles[] = {
"A Tale of Two Cities",
"Wuthering Heights",
"Don Quixote",
"Odyssey",
"Moby Dick",
"Hamlet",
"Gulliver's Travels"
};
char **bestBooks[3];
char **englishBooks[4];
bestBooks[0] = &titles[0];
bestBooks[1] = &titles[3];
bestBooks[2] = &titles[5];
englishBooks[0] = &titles[0];
englishBooks[1] = &titles[1];
englishBooks[2] = &titles[5];
englishBooks[3] = &titles[6];
printf("%s\n", *englishBooks[1]); //Wuthering Heights
return 0;
}
A statement like this:
char **bestBooks[3];
char **englishBooks[4];
Both arrays are declared as pointers to character pointers. Each array element contains a char
pointer to a pointer
The memory allocation for this example is as follows:
constants and pointers
pointer to constant
Defining a pointer as pointing to a constant means that the value it refers to cannot be modified through the pointer, but the pointer can be changed
The following statements are equivalent:
const int *pci
int const *pci
constant pointer to non-const
A constant pointer to non-constant means that the pointer is immutable, but the data it points to is mutable
constant pointer to constant
This kind of pointer itself cannot be modified, and the data pointed to cannot be modified through it.
const int * const pci = #
pointer to "const pointer to const"
Pointers to constants can also have multiple levels of indirection
int num = 100;
const int * const pci = #
const int * const *pcpci;
printf("%d\n", *pci); //100
pcpci = &pci;
printf("%d\n", **pcpci); //100