[C Language] Explanation of Arrays

Belonging column: C language
Blogger homepage: chuyang785
Code hosting: chuyang785
Thank you for your support, your likes and attention are the greatest support for me! ! !
Bloggers will also work harder to create better blog posts! !
Follow me, follow me, follow me, say important things three times! ! ! ! ! ! ! !

1. Creation and initialization of one-dimensional array

We have talked about many types before, such as our int, char, double, float, long and so on.
And when we often see a variable, we can only create a corresponding variable through one type.
But here comes the problem, what if we want to create a chain of variables of the same type? Is it still created one by one? If this is the case, it will not only waste our time, but also make the code we write cumbersome.

At this time, there is the concept of array.
An array is a collection of objects of the same type.

1.1 Creation of one-dimensional array

How the array is created:

type_t   arr_name   [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小

Here we [const_n] const_n does not have to be a constant expression, it can also be a variable, but it depends on our C standard.

For array creation, before the C99 standard, a constant must be given in [], and variables cannot be used. The C99 standard supports the concept of variable-length arrays. The size of the array can be specified using variables, but the array cannot be initialized.

An instance of array creation:

//代码1
int arr1[10];

//代码2
int count = 10;
int arr2[count];//数组时候可以正常创建?
//这种写法我们一般认为是错误的,但是在其他的语言或者C标准是支持这样写的。

//代码3
char arr3[10];
float arr4[1];
double arr5[20];

1.2 Initialization of one-dimensional array

Array initialization refers to giving some reasonable initial values ​​(initialization) to the contents of the array while creating the array.
Initialization method:

type_t   arr_name   [const_n]={num1,num2,……,mum(const_n)};
我们初始化的时候初始值使用一对{}括起来的,而我们的元素个数就是const_n个。

注释:
我们的字符串数组创建的时候也可以不用{}括起来,是可以用 "  "包含的:
char arr[3]="abc";

Let's look at the following way of creating an array:

int arr1[10] = {1,2,3};
int arr2[] = {1,2,3,4};
int arr3[5] = {1,2,3,4,5};
char arr4[3] = {'a',98, 'c'};
char arr5[] = {'a','b','c'};
char arr6[] = "abcdef";//对字符串特殊的定义数组方式。

Above we see that some arrays do not have a given size of the array, but directly initialize the value.
Let me explain here: == When creating an array, if you don't want to specify a certain size of the array, you have to initialize it. The number of elements in the array is determined by the content of the initialization ==. That is to say, you do not give the size of the array, but you give the initial value of the array. At this time, our compiler will automatically calculate the size of the array.

If we define an array: int arr[10]={1, 2, 3}; this is called an arrayincomplete initialization, as the name implies, the number we initialize is not equal to the size of our given array.
When incomplete initialization, if we do not assign a value to the array later, the compiler will initialize it to 0 by default.
insert image description here

Here we will systematically explain the string array:
above we said that the string array can be: char arr6[] = "abcdef"; this word definition.
From the surface, we see that the size of this array is 6, but in fact its size is 7, because a character \0 is hidden behind our string, but this character is not counted in the size of the array, so the size of the array It is 6.
insert image description here
Here we can see that there is a \0, and this \0 is used as the end mark of the string.

1.3 Use of one-dimensional arrays

For the use of arrays, we introduced an operator before: [] , the subscript reference operator. It is actually an operator for array access.
Before using it, let's understand the subscript of our array. In our programming, ourArray subscripts start from 0 by default.
Let's look at the code:

#include <stdio.h>
int main()
{
    int arr[10] = { 0 };//数组的不完全初始化
    //计算数组的元素个数
    int sz = sizeof(arr) / sizeof(arr[0]);
    //对数组内容赋值,数组是使用下标来访问的,下标从0开始。所以:
    int i = 0;//做下标
    for (i = 0; i < 10; i++)
    {
        arr[i] = i;
    }
    //输出数组的内容
    for (i = 0; i < 10; ++i)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

insert image description here
Here we need to understand how to calculate the size of the element group. We also mentioned the keyword sizeof() for calculating the size of the element group. sizeof (arr) calculates the byte size of the entire element group element, and our sizeof (arr[0]) is to calculate the byte size of an element, so that the total byte size/byte size of each element gets the number of elements.

1.4 Storage of one-dimensional arrays in memory

Now that we know that arrays are used to store data of the same type, how are these arrays stored in memory?
Is it stored randomly or sequentially in memory? Now let's explore:

The best way for us to explore is to print out the address of each element to find their rules.

#include <stdio.h>
int main()
{
 	 int arr[10] = {0};
	 int i = 0;
	 int sz = sizeof(arr)/sizeof(arr[0]);
 for(i=0; i<sz; ++i)
 {
 	 printf("&arr[%d] = %p\n", i, &arr[i]);
 }
	 return 0;
}

Here we add a knowledge point:%p is used to print the address
insert image description here
This is their printout.
Let's try to draw their memory distribution:
insert image description here
Note: Here, because the address is too long, we take out first and then 4 for comparison.
We assume that 0xF748 is our starting address, and add 0xF748 to our address in turn. The last address is 0xF749. At this time, let's compare the first element with the second element and our second element with the third element. , found that their difference is 4 bytes, and the type of the array we defined is int, and the size of the memory occupied by the int type is also 4 bytes.
We can also compare other elements:
insert image description here
we found that the address difference between the previous element and the next element is 4, so we know that the array is stored continuously in memory, and the size of each element is smaller than what we defined Depending on the type of the array.

Note: Another point is that our address is stored in hexadecimal, so here we convert it to decimal for calculation.

2. Creation and initialization of two-dimensional array

The so-called two-dimensional array is somewhat similar to our linear algebra, with rows and columns.
And our two-dimensional array is actually similar to a one-dimensional array, and even a two-dimensional array can be regarded as a one-dimensional array of a one-dimensional array.

For example:

1 2 3 4 
2 3 4 5
6 7 8 9

This is an array of three rows and four columns.

2.1 Creation of two-dimensional array

How to create a two-dimensional array:

type_t   arr_name   [row][col];
//row:表示有多少行
//col:表示有多少列

for example:

int arr[3][4];
char arr[3][5];
double arr[2][4];

2.2 Initialization of two-dimensional array

The initialization here is a bit similar to a one-bit array, and we just said that we can treat a two-dimensional array as a one-dimensional one-dimensional array through dimensionality reduction. That is to say, we can regard a row as the first element of a one-dimensional array, and so on.

In this way, when we initialize, we have to look like this:

int arr[3] [4]={ {1,2,3,4},{2,3,4,5},{3,4,5,6} };

Of course, it will work if we don't give {}:

int arr[3] [4]={ 1,2,3,4,2,3,4,5,3,4,5,6};

At this time, our compiler will automatically match.

What if we don't fully initialize? It is also initialized to 0 by default by the compiler like a one-dimensional array.

When we define a one-dimensional array, we can omit the size of the array. Does that mean that our two-dimensional array is also OK?
The answer is yes, but weOnly rows can be omitted, columns cannot be omitted

If we omit the column, we know the row but don't know how many elements there are in a row. At this time, the compiler doesn't know if there are enough elements in a row, and it doesn't know whether to initialize 0 by default. At this time, something goes wrong.

2.3 Use of two-dimensional arrays

The use of two-dimensional arrays is also through subscripts.

#include <stdio.h>
int main()
{
 	int arr[3][4] = {0};
 	int i = 0;
 for(i=0; i<3; i++)
 {
 		int j = 0;
		for(j=0; j<4; j++)
 		{
 			arr[i][j] = i+j;
  		}
 }
 for(i=0; i<3; i++)
 {
 		int j = 0;
 		for(j=0; j<4; j++)
 		{
 			printf("%d ", arr[i][j]);
 		}
 }
 return 0;
}

insert image description here

2.4 Storage of one-dimensional arrays in memory

Like 1D array, here we try to print the address of each element of 2D array.

#include <stdio.h>
int main()
{
 	int arr[3][4];
 	int i = 0;
 for(i=0; i<3; i++)
 {
 		int j = 0;
 		for(j=0; j<4; j++)
 		{
 			printf("&arr[%d][%d] = %p\n", i, j,&arr[i][j]);
 		}
 }
 return 0;
}

insert image description here
Similarly, we will find that
insert image description here
the difference between the address of its previous element and the next element is still 4, that is to say, its memory distribution is actually the same as that of a one-dimensional array, and the same array elements are stored continuously, and The size of the elements depends on the type of the defined array.

3. Array out of bounds

Array subscripts are limited in scope.
The subscript of the array starts from 0. If the array has n elements, the subscript of the last element is n-1.
Therefore, if the subscript of the array is less than 0, or greater than n-1, it means that the array is accessed out of bounds, and the access exceeds the legal space of the array.
The C language itself does not perform an out-of-bounds check for array subscripts, and the compiler does not necessarily report an error, but the fact that the compiler does not report an error does not mean that the program is correct.

For example:

#include <stdio.h>
int main()
{
 int arr[10] = {1,2,3,4,5,6,7,8,9,10};
    int i = 0;
    for(i=0; i<=10; i++)
   {
        printf("%d\n", arr[i]);//当i等于10的时候,越界访问了
   }
 return 0;
}

This type of our array size is 10, which means that our array subscripts are from 0-9, but in our for loop, the subscripts of the traversal array are obviously accessed from 00-10.

4. Arrays as function parameters

Often when we write code, we will pass an array as a parameter to a function, for example: I want to implement a bubble sort (here we will talk about the algorithm idea) function to sort an integer array.

4.1 Wrong Design of Bubble Sort

#include <stdio.h>
void bubble_sort(int arr[])
{
 int sz = sizeof(arr)/sizeof(arr[0]);//这样对吗?
    int i = 0;
 for(i=0; i<sz-1; i++)
   {
        int j = 0;
        for(j=0; j<sz-i-1; j++)
       {
            if(arr[j] > arr[j+1])
           {
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
           }
       }
   }
}
int main()
{
    int arr[] = {3,1,7,5,8,9,0,2,4,6};
    bubble_sort(arr);
    int i = 0;
    for(i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
   {
        printf("%d ", arr[i]);
   }
    return 0;
}

There seems to be no problem at all here, but when we run it, something goes wrong.
insert image description here
You will find that he did not sort at all.
Let's debug and take a look: we
insert image description here
found that sz here is 2. Logically, our sz should be equal to the size of the array, which is 10. Why is it like this?
At this time, we need to understand what the array name is.

4.2 What is the name of the array

Let's take a look at the code:

#include <stdio.h>
int main()
{
    int arr[10] = {1,2,3,4,5};
 	printf("%p\n", arr);
    printf("%p\n", &arr[0]);
    printf("%p\n", arr);
    //输出结果
    return 0;
}

insert image description here
We can see that these three addresses are the same, that is to say, the array name is the address of the first element of the array. (with two exceptions)

insert image description here
Why is 40 output here?
The reason is that the sizeof(arr) here is calculated by the small 10*4=40 of the entire array.

Let's look at this again:
insert image description here
we find that the address difference between &arr and &arr+1 is 40, which means &arr+1 skips the entire array.
However, the difference between the address of our arr+1 and arrr is 4, which means that arr+1 skipped an element.

The above amply says:

数组名通常是数组的首元素地址,但是有两个例外:
(1):sizeof(数组名)数组名单独放在sizeof()内部,这里的数组名表示整个数组,计算的是整个数组的大小

(2):&数组名,这里的数组名也表示整个数组,这里取出的是整个数组的地址。
除此之外遇到的数组名都表示数组的首元素的地址

This explains why the sz calculated above is equal to 2.
The reason is that we bubble_sort(arr); passed arr (not those two special cases), so arr here refers to the element address and when we receive, we accept an address, and sizeof(arr) calculates an address The size of the address depends on our hardware (the computer is divided into x32-bit and x64-bit, the size of an address for an x32-bit computer is 4 bytes, and the size of an address for an x64-bit computer is 8 bytes, and our computer is x64), so sizeof(arr)=8
and sizeof(arr[0]) calculates the size of an element, sizeof(arr[0]), 8/4==2 .
insert image description here

4.3 Correct Design of Bubble Sort Function

So the improved method here is to calculate sz in the main function, and then pass it by passing parameters.

void bubble_sort(int arr[],int sz)
{
    
    int size = sizeof(arr);
    int i = 0;
    for (i = 0; i < sz - 1; i++)
    {
        int j = 0;
        for (j = 0; j < sz - i - 1; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}
int main()
{
    int arr[] = { 3,1,7,5,8,9,0,2,4,6 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr,sz);
    int i = 0;
    for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

insert image description here

Guess you like

Origin blog.csdn.net/qq_74276498/article/details/130533723