C Language Array and Pointer Summary (Part I)

Keywords: P4 C

C Language Array and Pointer Summary (Part I)

1. Similarities:

a+n <=> (unsigned int) a+n * sizoeof (* a) If A is an array, a+n refers to the address of the nth element

p+n <=> (unsigned int) p+n * sizoeof (* p) If P points to an array, p+n points to the address of the nth element

    p[n] <=> *(p+n)  <=>* (n+p) <=> n[p]  ====   a[n] <=>*(a+n) <=>*(n+a) <=> n[a]

2. Differences:

Array space size sizeof(a) = sizeof(type)*n bytes

Pointer space size sizeof(p) = 4 bytes

Array names can be regarded as constant pointers, so arrays can not execute a++ or a-operator, but pointers are a variable, so p++ or p-operator can be executed.

3. On the meaning or operation of the & operator

& A = Array Address (Note: Array Address and Array Header Address have the same value but different meanings)

& P = the address of the pointer variable p

      &a+n = unsigned int(&a) + n*sizeof(*&a)

Unsigned int (& a) +n*sizeof (a) so it refers to the element after the entire array

& P + n = unsigned int (& p) + n * sizeof (& p) <=> unsigned int (& p) + n * 4 is the next 4 byte pointer

4. Four operations between pointer and pointer (+, -,*, /)

(a) Only subtraction operations are supported between pointers

(b) The types of pointers involved in subtraction operations must be the same

When two pointers point to the same array, p1-p2= (unsigned int (p1) - unsigned int (p2)/sizeof (type) means the subscript difference of the element indicated by the pointer.

When two pointers refer to different arrays for subtraction, they can be compiled and passed, but the result is meaningless. It only shows who is in front of memory allocation and who is in behind.

5. Relational operation between pointer and pointer (>, >=, <, <=, =!, ===)

(a) The premise of pointer relational operations is to point to elements in the same array at the same time

(b) Comparisons between any two pointers (=!, ===) are unlimited

(c) The types of pointers involved in comparison operations must be the same

In fact, I do not agree with the above three points, after testing different types of pointers can be compared, because all pointers are stored memory address, are four bytes, of course, can be compared, but the comparison is meaningless, can only explain the order before and after memory, no meaning.

6. Array names degenerate into pointer purposes when they are used as function parameters

C language takes efficiency as its initial design goal:

(a) When parameters are passed, the execution efficiency of copying the entire array will be greatly reduced

(b) Parameters are on the stack, too large an array copy will cause stack overflow

7. const modifies pointers

        const int* p1

        int const* p2;

        int* const p3;

        const int*const p4;

Regularity: left and right fingers

Meaning: const is on the left side of * and the pointer can't change the content, that is * p = 3 compilation error, but the pointer can change P = J

const is on the right side of * and the pointer is unchanged, that is, p=&j compilation error, but the pointer can be changed to the content, that is * p= 4.

const int* const p4 is on the left side of * and on the right side of * so it can't be changed, p= &j and * p = 5; both compile errors

The conclusion here is that you can write some code tests to impress yourself.

8. Here are some code examples

(1) Array and pointer differences:

#include <stdio.h>
int main()
{
    extern int a[];
    printf("&a = %p\n", &a);  //0x804a014 This is the array address.
    printf("a = %p\n", a);     //0x804a014 This is the address of the first element of the array
    printf("*a = %d\n", *a);   //1
    return 0;
}
ext.c
int a[] = {1,2,3,4,5}

Next, we will change the main function:

#include <stdio.h>
int main()
{
    extern int* a;
    printf("&a = %p\n", &a);  //0x804a014 This is the pointer address
    printf("a = %p\n", a);     //1  
    printf("*a = %d\n", *a);   //Segment error, because the pointer saves 1, so the value is taken according to this address, but this value is not allowed to operate in memory, so segment error
    return 0;
}
ext.c
int a[] = {1,2,3,4,5}

The above is the difference between pointers and arrays. If there is no difference, the theory should be compiled and passed, and the results should be the same, but if the compilation fails, the output results will be different.

(2) Multidimensional Pointer

#include <stdio.h>
int main()
{
   int value = 5;
   int* p1 = &value;
   int** p2 = &p1; //What will happen if you try to change this to int** P2 = value and then output ** p2? Under consideration
   int*** p3 = &p2;
   int**** p4 = &p3;
   
   printf("&value = %p\n&p1 = %p\n&p2 = %p\n&p3 = %p\n&p4 = %p\n\n",&value,&p1,&p2,&p3,&p4);
   
   printf("&value = %p\np1 = %p\n",&value,p1);
   printf("&p1 = %p\np2 = %p\n",&p1,p2);
   printf("&p2 = %p\np3 = %p\n",&p2,p3); 
   printf("&p3 = %p\np4 = %p\n\n",&p3,p4); 
   
   printf("*p4 = %p\np3 = %p\n&p2 = %p\n",*p4,p3,&p2);
   printf("**p4 = %p\np2 = %p\n&p1 = %p\n",**p4,p2,&p1);
   printf("***p4 = %p\np1 = %p\n&value = %p\n",***p4,p1,&value);
   printf("****p4 = %d\n\n",****p4);
   
   printf("*p3 = %p\np2 = %p\n&p1 = %p\n",*p3,p2,&p1);
   printf("**p3 = %p\np1 = %p\n&value = %p\n",**p3,p1,&value);
   printf("***p3 = %d\n\n",***p3);
   
   printf("*p2 = %p\np1 = %p\n&value = %p\n",*p2,p1,&value);
   printf("**p2 = %d\n\n",**p2);
   
   printf("*p1 = %d\n",*p1);
   
   return 0;
}

If you don't understand it, you don't fully understand the meaning of pointer.

(3) Pointer increment and decrement

Think about the following output, which are the same as, which are different from, and what are the differences. If you can answer all the questions correctly, you know the pointers and arrays very well.

* p++ and * (p++)

        (*p)++

* + + P and *(+ + p)

        ++*p

        *p+1

        *(p+1)

The difference between p+1 and p++

Differences between p++ and a++

What's the difference between p+1 and & p+1? If an array a+1 and & a+1 is different?


#include <stdio.h>

int main()
{
    int p1[] = {1,2,3,4,5};
    int* p3 = p1;
    int* p4 = p1;
    int* p5 = NULL;
    int a,b;
    printf("p3 = %p\np1 = %p\n",p3,p1);                  //p3 = p1 = 0xbfe4dbcc
    printf("&p3 = %p\n&p4 = %p\n&p1 = %p\n",&p3,&p4,&p1);//&p3 = 0xbfe4dbfc &p1 = 0xbfe4dbcc
    //Conclusion:
    //    & p3 is different from & p1 output, which is the obvious difference between pointers and arrays. & p3 is the address of the p3 pointer variable, while & p1 is the address of the array. (Note: the name of the p1 array represents the address of the first element of the array, and & p1 represents the address of the array, which means different, although their output values are the same.)
    a = *p3++;
    b = *(p4++);
    printf("a = %d\nb = %d\n",a,b);      //a=1  b=1
    printf("p3 = %p\np4 = %p\n\n",p3,p4);//p3 = p4 = 0xbfe4dbd0
    //Conclusion:
    //    Because the priority of + + operator is higher than *, so * p3++ is equivalent to * (p3++), which is the same as * (p4++). First calculate p3++, equal to p3, then * p3, and then increase the pointer by 1.
    p3 = p1;
    a = (*p3)++;
    printf("a = %d\np3 = %p\n",a,p3);//a=1 p3 = 0xbfe4dbcc
    printf("p1[0] = %d\n\n",p1[0]);  //p1[0] = 2
    //Conclusion:
    //    Since () priority is higher than ++, the first calculation (* p3) is equal to p1[0], that is, a=p1[0]+; so a=1,p[0] increases by 1, p[0]=2.
    
    p1[0] = 1;  //Because we changed this value above, we changed it to an initial value in order not to affect the following test results.
    
    p3 = p1;
    p4 = p1;
    a = *++p3;
    b = *(++p4);
    printf("a = %d\nb = %d\n",a,b);      //a = b = 2
    printf("p3 = %p\np4 = %p\n\n",p3,p4);//p3 = p4 = 0xbfe4dbd0
    //Conclusion:
    //    Because + + priority is higher than *, so * + + P3 is equivalent to *(+ + p3) = *(++p4), so first calculate + + p3, so that the pointer points to the array p1[1] address, and then executes the value, a = b = p1[1] = 2.
    p3 = p1;   
    a = ++*p3;
    printf("a = %d\np3 = %p\n",a,p3);  //a = 2  p3 = 0xbfe4dbcc
    printf("p1[0] = %d\n\n",p1[0]);        //p1[0] = 2
    //Conclusion:
    //    Because * and + + are both monocular operators, the order of operations is from right to left, ++* P3 is equivalent to ++(* p3), so first calculate (* p3)= p1[0], then increase by itself, that is + + p[0]; so p[0] = 2
    
    p1[0] = 1;  //Because we changed this value above, we changed it to an initial value in order not to affect the following test results.
    
    p3 = p1;   
    a = *p3+1;
    printf("a = %d\np3 = %p\n\n",a,p3);    //a = 2 p3 = 0xbfe4dbcc
    printf("p1[0] = %d\n\n",p1[0]);        //p1[0] = 1 
    //Conclusion:
    //    Because * p3 = p1[0], a = p[0] + 1 = 2
    p3 = p1;   
    a = *(p3+1);
    printf("a = %d\np3 = %p\n\n",a,p3);    //a = 1 p3 = 0xbfe4dbd0
    //Conclusion:
    //    First, we calculate P3 in (), then a = p3, and then p3+1.
    //p3 = p1 ++; // compilation error why array p1 + + compilation error, but pointer p3 + + can? Because the array name represents the address of the first element of the array, the array name can be regarded as a constant pointer, constant pointer can not be changed, so compilation error, and pointer is a variable, so it can be changed.
    p3 = p1;
    p4 = p1;   //Note: This is to see if there is a difference between p3 + + and p3+1, but since C is executed sequentially, it changes the following
    p3++;
    p5 = p4+1;
    printf("p3 = %p\np4 = %p\np5 = %p\n\n",p3,p4,p5);//p3 = 0xbfe4dbd0  p4 = 0xbfe4dbcc p5 = 0xbfe4dbd0
    //Conclusion:
    //    Through testing, we found that p3 and p5 are the same, so that is the result of p3 + + and p3+1 is the same, but p3 + + changed itself and pointed to the next element address, but p3+1 did not change itself, that is the difference.
    
    p3 = p1;    //This is to test if p3 +1 and & p3 +1 are different, and if p1 + 1 and & p1 + 1 are different at that time.
    p4 = p1;
    printf("p3 + 1 = %p\n&p4 + 1 = %p\n",p3 + 1,&p4 + 1);//p3+1=0xbfe4dbd0  &p4+1=0xbfe4dbd0
    printf("p1 + 1 = %p\n&p1 + 1 = %p\n",p1 + 1,&p1 + 1);//p1+1=0xbfe4dbd0 &p1+1=0xbfe4dbe0   
    //Conclusion:
    //    The output values of p3+1 and & p3+1 are not different, they are moving four bytes and the next element. But when you change P3 to char* p3, p3+1 = 0xbfe4dbcd, & p3+1 = 0xbfe4dbd0. This is the difference. The type of int is not different because both int and int* are four bytes, so it is different to change to char. The conclusion is that the data types pointed to by p3+1 and P3 are related. And there's no difference between & p3+1 and moving 4 bytes, because & P3 takes the type of pointer (note that it's not int * type), which seems to be a bit of a twist.
    //     The output of p1 + 1 and & p1 + 1 differs greatly from that of & p1 + 1 in that p1 + 1 moves four bytes and the next element address, while & p1 + 1 moves 20 bytes to the next address of the last element address of the array, so p1 represents the address of the first element of the array, and p1 represents the address of the array, which is a completely different concept.
    return 0;
}

The annotations are well explained, so there's no need to talk about them.


Major Reference to Ditty Software "C Language Advanced Course"


Posted by mika79 on Thu, 16 May 2019 15:08:48 -0700