c language array and pointer Foundation

This blog has a lot of references to c primer plus. I hope it will be more comfortable in the future

preface

In the c/c++ language, we all used arrays and pointers, but at the beginning, they were not very easy to handle. They made a lot of mistakes. The most difficult to use is the built-in type array of C language and the built-in type pointer. Because of the late appearance of c++, it absorbs the essence of C language, and has its own new ones, such as dynamic array vector, intelligent pointer, etc. But we also need to understand the most basic so that we can use C + + tools as much as possible without making too many mistakes.
This blog is based on the built-in type array and built-in type pointer of c language.

Array (array subscript starts from zero)

Array: consists of a series of elements with the same data type. When using an array, you should tell the compiler how many elements are in the array and what the type of the element is through a declaration.

Let's look at the declaration and initialization of the array through the code:

#include<stdio.h>
int main(){
     //Declare but not initialize the array. The storage elements in the array are garbage values
	 int array[5];//There are five int elements in the array 
	 float array_1[2];//  array_ There are 2 elements of float type in 1 
	 
	 //Initialization of array
	int apple[6]={1,2,3,4,5,6};//This initialization is supported from ANSI C
	int arr[5]={1,2,3}; //The compiler will set the following two int elements to 0 / / that is, the elements are 1,2,3,0,0
			
			
			
	//int ar[6]={0,0,0,0,0,1}; // Traditional grammar
	// c99 initializers can be specified 
	int ar[6]={[5]=1};// Initialize ar[5] to 1, and set other int types in the array to 0, / / that is, the element is 0,0,0,0,1 
			 
	return 0;
} 

The array requirements of c language are strict, and the assignment between arrays is not allowed, but the c compiler will not check the out of bounds of the array and the correctness of the array index

int arr[3];
int app[4];
app=arr;// [Error] assignment to expression with array type

Array subscript out of bounds may lead to program crash. It is the programmer's responsibility to use the array without out of bounds

The value of [] of array requires an integer constant expression
Type and 1 are integer constants, and sizeof expressions are treated as integer constants
And the value inside [] must be greater than 0

int array[sizeof(int)] //ok integer constant expression
int arr[-1] //error array size must be greater than 0
int arr[0] // error array size must be greater than 0
int arr[1.2] //error array size must be an integer
int arr[(int)1.2] // ok has been strongly converted to plastic surgery

c 99 allows the declaration of an array called variable length array (VLA)

int a=3;
int arr[a] //ok

This array will not be introduced first.

When we don't want to change the elements in the array, we can use the const qualifier to indicate that the array is read-only and the variables in it are not allowed to be modified.

#include <stdio.h>
int main()
{          /*letting the compiler count elements */
    const int days[] = {31,28,31,30,31,30,31,31,30,31};//Represents the number of days in the month of a year, except leap years 
    int index;
    for (index = 0; index < sizeof days / sizeof days[0]; index++)
     printf("Month %2d has %d days.\n", index +1,
               days[index]);
     days[1]=29; //	[Error] assignment of read-only location 'days[1]'
    return 0;
}

Now let's repeat a few important words just now, quite important words:
1. The array has the characteristics of container. The array stores the same data type
2. The size of the array must be given at compile time
3. The elements in the array are arranged continuously in memory, so random access is supported
4. When using an array, the number placed in [] is called a subscript. The subscript of the array starts from zero and must be greater than 0
5. Array subscript out of bounds may lead to program crash. It is the programmer's responsibility to use the array without out of bounds
6. Most of the time, the array name represents the address of the beginning of the array (there are two special cases) (I'll talk about the pointer right away)

Pointer (built-in type)

A pointer is a variable whose value is a memory address
Since the pointer is a variable, the variable must be given a value. Yes, yes, the value given to the pointer is the physical address of other variables. We get the physical address of a variable by using the & operator

int* ptr=NULL; //ptr is a pointer variable of type int *
int a=3; //A is an int variable with a physical address in memory, & 3
ptr=3;// The GCC compiler of c language will give warning, indicating that the type check of c language is not strict, and c + + will give error. Don't ignore warning
ptr=&3; //The pointer has obtained the address of variable a
int b=*ptr; //Use the dereference operator to get the value of the address pointed to by the pointer

Well, we now know the basic usage of pointer. The pointer represents the address of manipulating data, which is equal to manipulating data. Let's practice more.
We will continue to explore their more advanced usage through pointers and arrays.
Let's look at pointers and arrays

Pointers and arrays

Here we should remember that the name of the array represents the address, which represents the address of the beginning of the array,
Look at the picture:

Therefore, we can use pointers to manipulate arrays!

 float array[5]={1,2,3,4,5} //This is an array of float type, containing 5 data elements
 float* ptr=array; //Assign the first address of the array to ptr, because the array name is the address, so we can't use &, and it will become another meaning!
 for(size_t i=0;i<5;i++){
   printf("%p",*(array+i)); // Traversing an array using a pointer
}

We now give a code in the book, which is more detailed:
Code source (c primer plus)

// pnt_add.c -- pointer addition
#include <stdio.h>
#define SIZE 4
int main(void)
{
    short dates [SIZE];//This is a short array with four elements  
    short * pti;  //This is a pointer to the short type 
    short index;  //This is to declare a variable 
    double bills[SIZE]; //This is an array of double type, containing four elements 
    double * ptf; //This is a pointer to type double 
    
    pti = dates;    // assign address of array to pointer
    ptf = bills;
    
    printf("%23s %15s\n", "short", "double");
    for (index = 0; index < SIZE; index ++)
        printf("pointers + %d: %10p %10p\n",
          index, pti + index, ptf + index);
    
    return 0;
}

In my system computer, short takes up 2 bytes and double takes up 8 bytes. The following is the exe executed by the gcc compiler,

We need to remember a sentence: the pointer increases by 1, and the increment is the size of the type it points to.
Next, the blogger directly wrote out the usage of pointers and summarized (the built-in types of pointers contain characteristics, while c + + sets iterators (generalized pointers) to different levels. For specific understanding, please go to Baidu)
1. Assignment: pointers can be assigned directly, but attention should be paid to the compatibility of types on both sides of the equal sign. (the type check of c language is not as strict as that of c + +. c language can assign numbers to pointers, but c + + can't)

Int * PTR1 = & 1; / / PTR1 is a pointer variable of type int * in which the address of 1 is stored
int* ptr2; //ptr2 is a pointer variable of type int *
ptr2=ptr1; / / assign the content (address) in the ptr1 variable to ptr2 through the assignment between pointers
Look at this picture

(the blogger doesn't quite understand)
This built-in type pointer points to the stack area and static storage area, and the assignment is not easy to make mistakes. However, when the built-in type pointer points to the heap storage area, many problems will occur, such as:
As we can see in the figure, two pointers point to the same content. If you release memory, it is very easy to make operation errors. This is the problem of deep copy and shallow copy. You can go to Baidu by yourself.)

2. Dereference operation: we can use the * operator to obtain the contents stored in the pointer variable
3. Take address: since the pointer is also a variable, the variable must have an address in memory. We can use &, to get the address of the pointer.
4. Adding pointers and integers: This is also a pointer, but the step size of the pointer is modified. It is often used when using pointers to process arrays
5. Increment pointer: when the pointer points to the array, the pointer is incremented, as mentioned earlier: the pointer is incremented, and the increment is the size of the type it points to
6. Subtract a number from the pointer
7. Decrement pointer
8. Pointer subtraction: the premise that two pointers can be subtracted is that these two pointers point to arrays of the same type, and we get the distance
9. Comparison: the premise that two pointers can be compared is that these two pointers point to arrays of the same type
10. Used as the judgment condition of the loop: we can use it in some loop expressions to judge
Above, you don't need oral memory, just practice more

Next, we will several important formulas:

int array[5]={1,2,3,4,5};
int* ptr=arrar;
/*The following two equations are the same*/
*(array+2)=array[2]; //Are the elements of the array

/*The following two equations are the same*/
array+2=&array[2]//Are the addresses of array elements

Practice more and you'll remember.

Pointers are used in conjunction with the increment and dereference operators
Sometimes, when we look at the code written by some experts, they often write the code of several steps in one line, such as:

*p++
*++p
(*p)++
How should I understand you?

Let's read the code in the book first:

#include <stdio.h>
int data[2] = {100, 200};
int moredata[2] = {300, 400};
int main(void)
{
    int * p1, * p2, * p3; //Define pointer 
    
    p1 = p2 = data;
    p3 = moredata;
    printf("  *p1 = %d,   *p2 = %d,     *p3 = %d\n",
           *p1     ,   *p2     ,     *p3);
    printf("*p1++ = %d, *++p2 = %d, (*p3)++ = %d\n",
           *p1++     , *++p2     , (*p3)++);
    printf("  *p1 = %d,   *p2 = %d,     *p3 = %d\n",
           *p1     ,   *p2     ,     *p3);
    
    return 0;
}

Look at the operation results;

analysis:
The unary operators * and + + have the same priority, but the association law is from left to right,
*p1++:
p1++: it is advanced in expression operation, and the pointer returned is the pointer before computation.

Similar implementations of i + + are:
int temp ;
temp=i;
i=i+1; // Expression operation
return temp; // temp records the value of the previous i and returns the previous value

* p1 at the beginning; So what you get is the first value of the sequence, 100

*++p2: increment the pointer first,

++Similar implementation of i
i=i+1;
Return I / / the value of I has been incremented

* p2 / / the pointer points to the next element
So what you get is the second element of the sequence! two hundred

However, it should be noted that:
++Both i and i + + can increment i, but pay attention to the difference between them in assignment

(* p3) + +: this should be easy to analyze. After the pointer is dereferenced, the value is + 1 and 301 is obtained

Note: + + p1 and p2 + + do not change the value of the array, but (* p3) + + does change the value in the array.

Well, that's all for this blog.

Tags: C C++

Posted on Sun, 12 Sep 2021 23:12:18 -0400 by php_guest