C Language Pointer Array and Array Pointer--Introduction

1. Memory layout of pointer array and array pointer

Beginners can't always tell the difference between pointer array and array pointer. In fact, it is easy to understand:

Pointer array: First, it is an array. The elements of the array are pointers. The number of bytes in the array is determined by the array itself. It is short for "array of pointers."

Array pointer: First, it is a pointer, which points to an array. In a 32-bit system, it always occupies 4 bytes. As for how many bytes it points to, I don’t know. It is short for "pointer to array".

下面到底哪个是数组指针,哪个是指针数组呢:
A)
int *p1[10];
B)
int (*p2)[10];
每次上课问这个问题,总有弄不清楚的。这里需要明白一个符号之间的优先级问题。

"[]" has a higher priority than "*" . p1 is first combined with "[]" to form the definition of an array. The array name is p1, and int * modifies the content of the array, that is, each element of the array.

Now we know that this is an array, which contains 10 pointers to int type data, that is, an array of pointers. As for p2, it is better to understand. Here, the priority of "()" is higher than that of "[]". The "*" sign and p2 constitute the definition of a pointer. The pointer variable is named p2, and int modifies the contents of the array. That is, each element of the array.

The array does not have a name here, it is an anonymous array. Now we know that p2 is a pointer, which points to an array containing 10 int type data, that is, an array pointer . We can use the following diagram to deepen our understanding:Insert picture description here

2. int (*)[10] p2-----maybe the array pointer should be defined like this

Here is an interesting topic worth discussing: don't we usually define pointers with pointer variable names after data types? Why is the definition of the pointer p2 not defined according to this syntax? Maybe we should define p2 like this:

   int (*)[10] p2;

int (*)[10] is a pointer type, and p2 is a pointer variable. This looks good, but it looks a little awkward. In fact, the prototype of the array pointer is indeed like this, but the pointer variable p2 is moved forward for convenience and beauty. You can understand this in private. Although the compiler does not think so. _

3. Discuss the difference between a and &a again

In this case, the problem is here. Earlier we talked about the difference between a and &a, now let’s take a look at the following code:

int main()
{
   char a[5]={'A','B','C','D'};
   char (*p3)[5] = &a;
   char (*p4)[5] = a;
   return 0;
}

Which of the above uses of p3 and p4 is correct? What will be the value of p3+1? What will be the value of p4+1?
There is no doubt that p3 and p4 are array pointers, pointing to the entire array. &a is the first address of the entire array, a is the first address of the first element of the array, its value is the same but the meaning is different.

In C language, the data types on both sides of the assignment symbol "=" must be the same. If they are different, explicit or implicit type conversion is required. The data types on both sides of the "=" in the definition of p3 are exactly the same, while the data types on both sides of the "=" in the definition of p4 are inconsistent.

The type on the left is a pointer to the entire array, and the data type on the right is a pointer to a single character. The following warning is given on Visual C++ 6.0:

   warning C4047: 'initializing' : 'char (*)[5]' differs in levels of indirection from 'char *'。

Fortunately, although a warning is given here, since the value of &a and a are the same, and when the variable is used as an rvalue, the compiler just takes the value of the variable, so there is no problem in running. But I still warn you not to use this.

Now that it is clear that both p3 and p4 point to the entire array, the values ​​of p3+1 and p4+1 are easy to understand.

But if you modify the code, what will be the problem? What are the values ​​of p3+1 and p4+1?

int main()
{
   char a[5]={'A','B','C','D'};
   char (*p3)[3] = &a;
   char (*p4)[3] = a;
   return 0;
}
甚至还可以把代码再修改:
int main()
{
   char a[5]={'A','B','C','D'};
   char (*p3)[10] = &a;
   char (*p4)[10] = a;
   return 0;
}

What kind of problems will there be at this time? What are the values ​​of p3+1 and p4+1?

I hope readers can carefully consider the above issues.

Four, address forced conversion

Consider the following example first:

struct Test
{
   int Num;
   char *pcName;
   short sDate;
   char cha[2];
   short sBa[4];
}*p;
假设p 的值为0x100000。如下表表达式的值分别为多少?
   p + 0x1 = 0x___ ?
   (unsigned long)p + 0x1 = 0x___?
   (unsigned int*)p + 0x1 = 0x___?

I believe that many people will not understand what this question means at first. In fact, if we take a closer look, this knowledge seems familiar. How to parse a pointer variable and an integer?

Remember the difference between our expression "a+1" and "&a+1" earlier?

Actually it's the same here. Adding and subtracting a pointer variable to an integer is not directly adding or subtracting the integer with the address in the pointer variable. The unit of this integer is not byte but the number of elements.

So: the value of p + 0x1 is 0x100000+sizof(Test)*0x1. As for the size of this structure is 20byte, it has been explained in detail in the previous chapters. So the value of p +0x1 is: 0x100014.

What about the value of (unsigned long)p + 0x1?
This involves coercion, coercing the value stored in the pointer variable p into an unsigned long integer. Once any value is coerced, its type is changed.
So this expression is actually an unsigned long integer plus another integer. So its value is: 0x100001.

What about the value of (unsigned int*)p + 0x1?
The p here is coerced into a pointer to an unsigned integer. So its value is: 0x100000+sizof(unsigned int)*0x1, which is equal to 0x100004.

The above question does not seem to have any technical content. Here is a technical content: What is its value under the x86 system?

intmain()
{
   int a[4]={1,2,3,4};
   int *ptr1=(int *)(&a+1);
   int *ptr2=(int *)((int)a+1);
   printf("%x,%x",ptr1[-1],*ptr2);
   return 0;
}

This is a question that a student asked me during my lecture. He saw it on the Internet. It is said that it has stumped n people. After reading the questions, I told him that these people certainly don't understand assembly. For a person who understands assembly, this kind of question is really a small case. Let's analyze and analyze this problem below:

According to the above explanation, the difference between &a+1 and a+1 is clear.

ptr1: Coercively convert the value of &a+1 to int type, and assign it to the variable ptr of type int . ptr1 must point to the next int type data of array a. ptr1[-1] is parsed as *(ptr1-1), that is, ptr1 goes back 4 bytes. So its value is 0x4.
ptr2: According to the above explanation, the value of (int)a+1 is the address of the second byte of element a[0]. Then cast this address to an int type value and assign it to ptr2, which means that the value of ptr2 should be the content of 4 consecutive bytes starting from the second byte of element a[0].

The memory layout is as follows:
Insert picture description here
Okay, here comes the problem, what exactly is stored in these 4 consecutive bytes? In other words, how are the values ​​in the elements a[0] and a[1] stored. This involves the large and small endian modes of the system. If you understand assembly, this is not a problem at all. Since you don't know what mode the current system is, you have to find a way to test it. The small-endian mode and the testing method have been discussed in detail when the union keyword was explained in Chapter 1, please turn to the other place to see it, and I won't go into details here. We can use the following function to test the current system mode.

int checkSystem( )
{
   union check
   {
      int i;
     char ch;
   } c;
   c.i = 1;
   return (c.ch ==1);
}

If the current system is in big-endian mode, this function returns 0; if it is in little-endian mode, the function returns 1. That is to say, if the return value of this function is 1, the value of *ptr2 is 0x2000000. If the return value of this function is 0, the value of *ptr2 is 0x100.

Original link: http://c.biancheng.net/cpp/html/476.html

Guess you like

Origin blog.csdn.net/zhuyin6553/article/details/88380782