1. Ask questions
#include <stdio.h>
int main()
{
char array[16] = {
'A', 'B'};
char (*parray)[16] = &array;
printf("========================\n");
printf(" array: \t%#lx\n", array);
printf("& array: \t%#lx\n", &array);
printf("&* array: \t%#lx\n", &*array);
printf("*& array: \t%#lx\n", *&array);
printf(" parray: \t%#lx\n", parray);
printf("* parray: \t%#lx\n", *parray);
printf("*& parray: \t%#lx\n", *&parray);
printf("&* parray: \t%#lx\n", &*parray);
printf("========================\n");
return 0;
}
The outputs of array &array &*array *&array parray *parray *&parray &*parray in the above program are the same. All are 0x61ff10 on the test computer (as shown in the figure below), what is the reason? The following is a step-by-step analysis, and the conclusion is at the end of the article.
2. Solutions
The first group: array has the same value as &array
#include <stdio.h>
int main()
{
char array[16] = {
'A', 'B'};
char (*parray)[16] = &array;
printf(" array: \t%#lx\n", array); // 输出 0x61ff10
printf("& array: \t%#lx\n", &array); // 输出 0x61ff10
printf("数组array的第二元素的地址: \t%#lx\n", array+1); // 输出 0x61ff11
printf("数组array的下一数组的地址: \t%#lx\n", &array+1); // 输出 0x61ff20
printf("数组array的第二元素的地址: \t%c\n", *(array+1)); // 输出字符 B
printf("数组array的下一数组的地址: \t%c\n", *(&array+1));// 输出为空
printf(" array: \t%d\n", sizeof(array)); // 输出 16,整个数组array的大小也为16,即array代表整个数组
printf(" array: \t%d\n", sizeof(&array)); // 输出 4,则 &array 应为指针变量
printf(" array: \t%d\n", sizeof(array+1)); // 输出 4,因为 array+1 时,array 隐式转换为指针变量了
return 0;
}
array
It is the name of the array with a length of 16, which can be understood as an array object. When array+1, it will be implicitly converted to the address of the first element of the array;&array
It is a pointer variable with a length of 4, indicating the address of the entire array array, but the value is equal to the address of the first element of the array.
Although the values are the same, the contents are different. In the above code, array + 1 indicates the address of the second element of the array, and &array + 1 indicates the "next array" of the entire array array, that is, it points to the next address at the end of the array array.
Note: The compiler is 32-bit when testing on this machine, so the length of the pointer variable is 4 1
The second group: &*array and *&array
#include <stdio.h>
int main()
{
char array[16] = {
'A', 'B'};
char (*parray)[16] = &array;
printf("&* array: \t%#lx\n", &*array); // 输出 0x61ff10
printf("*& array: \t%#lx\n", *&array); // 输出 0x61ff10
printf("&* array: \t%d\n", sizeof(&*array)); // 输出 4,数组首元素的地址
printf("*& array: \t%d\n", sizeof(*&array)); // 输出 16,*&array 等价为 array
printf("*&*array: \t%c\n", *&*array); // 输出 A
printf("**&array: \t%c\n", **&array); // 输出 A
return 0;
}
&*array
It is a pointer variable with a length of 4. array is the name of the array, *array is the first element of the array, so &*array is the address of the first element of the array, and its length is 4, and its type is a pointer variable.*&array
It is an array with a length of 16. &array is a pointer variable, pointing to the entire array. Dereference the pointer &array pointing to the entire array once, and get the object of the entire array.
On the other hand, * and & are reciprocal operators, which can be understood as canceling each other on the surface. But it should be noted that the value of sizeof(&*array) is 4, that is, &*array is a pointer variable; sizeof(*&array) is 16, that is, *&array is equivalent to array, which means an array object.
The third group: parray and *parray
#include <stdio.h>
int main()
{
char array[16] = {
'A', 'B'};
char (*parray)[16] = &array;
printf(" parray: \t%#lx\n", parray); // 输出 0x61ff10
printf("* parray: \t%#lx\n", *parray); // 输出 0x61ff10
printf(" parray: \t%#lx\n", parray+1); // 输出 0x61ff20,则 parray 指向整个数组
printf("* parray: \t%#lx\n", *parray+1); // 输出 0x61ff11,则*parray 指向数组首个元素
printf("**parray: \t%c\n", **parray); // 输出 A
printf(" parray: \t%d\n", sizeof(parray)); // 输出 4
printf(" parray: \t%d\n", sizeof(*parray)); // 输出 16
return 0;
}
parray
It is a pointer variable of type char int (*)[16] with a length of 4. As can be seen from the declaration, the pointer is equivalent to &array, that is, it points to the array object array.*parray
Indicates that the pointer variable parray is dereferenced once, that is, the object of the array array is obtained, and its length is 16, which is equivalent to the array name array. For example, the values of (*parray)[0] and array[0] are both a. And *array, after implicit conversion of the array name, is expressed as the first element of the array, so if it is dereferenced again, ie **parray means the first element of the array array: A.
The fourth group: *&parray and &*parray
#include <stdio.h>
int main()
{
char array[16] = {
'A', 'B'};
char (*parray)[16] = &array;
printf("*&parray: \t%#lx\n", parray); // 输出 0x61ff10
printf("*&parray: \t%#lx\n", *&parray); // 输出 0x61ff10
printf("&*parray: \t%#lx\n", &*parray); // 输出 0x61ff10
printf("*&parray: \t%d\n", sizeof(*&parray)); // 输出 4
printf("&*parray: \t%d\n", sizeof(&*parray)); // 输出 4
printf("*&parray的下一单元: %#lx\n", *&parray+1); // 输出 0x61ff20
printf("&*parray的下一单元: %#lx\n", &*parray+1); // 输出 0x61ff20
return 0;
}
There is nothing to talk about in this group, just understand it as *& offset. Note that the parray in the code is 0x61ff10, while *&parray+1 and &*parray+1 are both 0x61ff20, which proves again that parray points to the entire array, and its function is equivalent to &array.
3. Conclusion
char array[16] = {
'A', 'B'};
char (*parray)[16] = &array;
In the above code, array
it is the name of the array, let's understand it as the object of the array, when the operation is performed on the array, "implicit conversion" will occur. Through sizeof(array), its length is 16, that is, the length of the array. Therefore, array should not be a pointer in essence, but when performing operations, such as array + 1, array will be implicitly converted into a pointer variable pointing to the first element of the array, while array + 1 points to the second element of the array. &array
It means a pointer variable pointing to the entire array, its type is int (*)[16], and &array + 1 will span the entire array array and point to the next "array" (if it exists) .
It can be seen from the variable declaration that is parray
equivalent to &array, and *parray
is equivalent to *&array (ie array), which is the name of the array and represents the array object. When performing operations, *parray will be implicitly converted like array.
The following excerpt is from page 213 of the book "C++ Primer Plus" 2 :
Supplementary extension
#include <stdio.h>
int main()
{
char array[16] = {
'A', 'B'};
char (*parray)[16] = &array;
printf(" array: \t%c\n", (&array[0])[0]); // 输出 A
printf(" array: \t%c\n", (&array[0])[1]); // 输出 B
printf(" array: \t%c\n", (&array[1])[0]); // 输出 B
printf(" array: \t%c\n", (&array[1])[1]); // 输出 空
return 0;
}
#include <stdio.h>
int main()
{
char array[16] = {
'A', 'B'};
char (*parray)[16] = &array;
printf(" parray: \t%#lx\n", parray); // 输出 0x61ff10
printf("* parray: \t%#lx\n", *parray); // 输出 0x61ff10
printf(" parray: \t%c\n", parray[0][0]); // 输出 A
printf(" parray: \t%c\n", parray[0][1]); // 输出 B
// printf(" parray: \t%c\n", parray[1][0]); // 输出 空
// printf(" parray: \t%c\n", parray[1][1]); // 输出 乱码
printf(" parray: \t%c\n", *parray [0]); // 输出 A
printf(" parray: \t%c\n", (*parray)[1]); // 输出 B
printf(" parray: \t%c\n", **parray ); // 输出 A
printf(" parray: \t%c\n", **parray+1); // 输出 B
return 0;
}
The above problems and solutions are based on the test results. Due to my limited knowledge, please point out the mistakes in the text.
reference link
[1] How many bytes does a pointer variable in C language occupy [ 2
] When does an implicit conversion occur ? Edition page 213