The nature of pointer
What is a pointer
Essentially, what must be emphasized is that pointer is a data type in C context, like int data type. Therefore:
pointerneed memory space to store.pointerhas its own address of the memory space.
In computer science, a pointer is a programming language object that stores the memory address of another value located in computer memory. A pointer references a location in memory, and obtaining the value stored at that location is known as
dereferencingthe pointer. —WIKI)
Given these points, we can say that pointer is a data type which is intended to store the memory address. More importantly, we can obtain the value of the pointer by dereference operation.
Memory address of pointer
Since we have known that pointer is used to store the memory address, then what is the memory address? It can be diagrammed by the figure below:

This is the memory figure of the below code:
unsigned char a = 7; // unsigned char only contain 1 bit
unsigned char* pa = &a; //assign the address of a to pointer b
unsigned char** ppa = &b; //assign the address of the pointer pa to pointer ppa
printf("dereferencing ppa = %d\n", **ppa);
It can be explained that the variable unsigned char a is initialized with 7, and stored at 0x00 memory space. Then referencing variable a to pointer pa. It means that acquiring the address of variable a and assigning it to pointer variable pa.
Note: here you can see:
The valueof pointerpais0x00, i.e. the address of variablea.The addressof pointerpais0x01, i.e. the address of pointerpaitself.
It is what we mentioned before, the pointer pa is a data type and it has its own address. The deference operation means that obtaining the value of the address stored in the pointer(i.e., the value of pointer).
The situation is similar to the pointer ppa, it means the pointer ppa to the other pointer pa. The value of the pointer ppa is the address of the pointer pa. And the pointer ppa has its own address 0x02.
The type of the pointer
Firstly, the pointer is intended to store the address, however, the address is only a series of numbers. Therefore, the different types are not necessary for pointers in terms of the pointer itself. However, there is the most important reason that we need different type of pointers in terms of dereference operation:Tell the compiler how to interpret the variable.

Specifically, when we acquire the address from the pointer pb(i.e. 0x00), we only know the variable b start from the 0x00 in the memory space. We don’t know how many blocks the variable b contains. We must tell the compiler that pb is a int* type pointer, then the compiler will know that we need to obtain the first 4 blocks of this memory to interpret the variable b(because the int type contains 4 bytes).
void pointer
Specially, void pointer can transfer to arbitrary type pointer(e.g. int*, char*) with necessary explicit type conversion. But arbitrary type pointer transfer to void pointer without any conversion.
void* p;
int* pa = (int *)p; // explicit type conversion
float f = 1.22f;
float* p1 = &f;
p = p1; // without any conversion
The reason that why we need to execute the type conversion explicitly is that we need to tell the compiler how many blocks of the memory are used to interpret the variable.
Typically, the void pointer is intended as the parameters of the function which the type of the pointer is uncertain. For example:
void* memcpy(void *addr1, void *addr2, size_t n);
It means arbitrary pointer type can pass to this function, because it is only need to operate the memory, the type of the pointer is inessential.
Pointer operation
Firstly, the operation of pointer means the operation of the value of pointer.
As the figure:

Please note that in this stage, the pointer pb is stored in 0x20 instead of 0x04. Then
pb+1 ==> 0x00 + 4 ==> 0x04
We can see that the addition of pointer is the value of the pointer add the sizeof(type) bytes. Therefore, it is pointless of the addition of pointer, because it is hard to explain what is in memory 0x04(or even 0x04 memory block does not exit).
In some cases, the subtraction is allowed in C because we can the offset of two pointers.
array name Vs. pointer
Conclusion
Array is array, pointer is pointer, they are different data type. Essentially, pointer is a variable, array name is a symbol(constant).
Analysis
int main(void) {
int a[5] = {1,2,3,4,5};
int (*pa)[5] = &a;
int* paEle = a;
//exp1
printf("%d\n", sizeof(a)); //20
printf("%d\n", sizeof(paEle)); //8
//exp2
printf("%p\n", &a); // 0x7ffdb136eb30
printf("%p\n", a); // 0x7ffdb136eb30
//exp3
printf("%p\n", a); // 0x7ffdb136eb30
printf("%p\n", pa); // 0x7ffdb136eb30
printf("%p\n", a+1); // 0x7ffdb136eb34
printf("%p\n", paEle+1); // 0x7ffdb136eb34
printf("%p\n", pa+1); // 0x7ffdb136eb44
printf("%d\n", *(a+1)); // 2
printf("%d\n", *(pa+1)); // -1321800892
return 0;
}
- In terms of the
exp1, From thesizeofresult, it can be concluded that thearray nameandpointerare different. Because ifais a pointer, thensizeof(a)should be equal to8(64-bit machine). - As for the reason that the results of
exp2are equal, it is that when thearrayare passed as the parameters of function, then it will decay to thepointer. - With respect to the
exp3,pa+1(i.e. the pointer to the arraya) means the offset will be the whole array. This is why the result of*(pa+1)is a random value. However, the offseta+1andpaEle+1are one element(4 bytes forint).
Differences
1. Declaration:
Except the situation that passed as the parameter, array name and pointer are totally different. Below is a wrong example:
char a[]; //define an array in `a.c` file,
extern char* a; //declare a as a pointer in other file, cannot compile(gcc not sure)
2. pointer is a variable, array name is a constant
- The essential of
array nameis the address of the first element of an array. In assembly code, it is a constant. Therefore, it can not++or--. In fact, typically, thea[i]will be transfered to*(a+i). a, i.e. the address of the first element of array can be acquired in the compilation stage. In the assembly code, the address of the array are solid. For example, assuming that the address ofais0x8048000, thena[1]will be transfered to*(0x8048000 + 4), (intare 4 bytes). However, pointer is a variable, the value cannot be acquired when compiling.- Reference to array(
a[1]) will access the memory1time, reference to pointer*(p+1)will access the memory 2 times. Becauseais the constant, what need to do is use constantaplus1and deference the address to the value. However, pointer is a variable, need to deference it firstly and plus1, and then deference the obtained address.
pointer to array Vs. array of pointers
int *array1[10]; // An array of pointers. Each element of this array is one pointer.
// There are 10 pointers in total
int (*array2)[10]; // A pointer to an array. Each element of this array is one integer.
// There are 10 integers in total, and a pointer to this array.
int *(array3[10]); // same as the first one. An array of pointers.
The reason is that the operator precedence of
[](array subscripting)is higher than* (dereference).
In fact,
- In the first case, initially is the
array1[10]operation, i.e. an arrayarray1[10], then is the*array1[10]operation, i.e. each element of this array is one int pointer. - In the second case, the bracket
()improves the operator precedence of*to the same level of[]. The practical associativity order is (*array2) firstly, i.e., a pointerarray2, then is an array of ten integers.
Initialize array of pointers
double *pos[10];
pos[0] = calloc(10*5,sizeof(double));
for(i=1;i<10;i++){
pos[i] = pos[0] + i * 5;
}
Here, we cannot do this: pos = calloc(10*5, sizeof(double)) directly, because here pos is the array name, it is a constant!
2-d array of pointers
int (*a[10])[5]; // a is an array of pointers, each pointer to an array of 5 integers.
Here, using the bracket () to associate the * with the first dimension a[10], i.e., the first dimension is an array pointers, and then the second dimension is the [5]. In a word, what each element within a points to is an array with 5 integers.
In other words, a is an array of pointers, there are 10 pointer within a in total, each element is a pointer to an array with 5 integers.
References:
- pointer
- pointer type
- void pointer
- void pointer 2
- array name and pointer
- array name assembly
- array of pointers
- operators in C
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 gzrjzcx@qq.com
文章标题:The nature of pointer
文章字数:1.5k
本文作者:Alex Zou
发布时间:2019-02-22, 13:37:59
最后更新:2024-07-10, 03:02:36
原始链接:https://www.hellscript.cc/2019/02/22/subposts_c/The-nature-of-pointer/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。