【C/C++】Array pointer: array address &array *parray dereferencing **parray twice with the same value

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.

insert image description here

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;
}
  1. arrayIt 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;
  2. &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;
}
  1. &*arrayIt 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.
  2. *&arrayIt 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;
}
  1. parrayIt 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.
  2. *parrayIndicates 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, arrayit 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. &arrayIt 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 parrayequivalent to &array, and *parrayis 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 :

insert image description here

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


  1. 2 ↩︎

  2. 4 ↩︎

Guess you like

Origin blog.csdn.net/Alpherkin/article/details/131482910