This is the fifth day of my participation in the November Gwen Challenge. Check out the details: The last Gwen Challenge 2021

An array of

A one-dimensional array

create
define

An array is a collection of elements of the same type. The syntax for the array is:

type_t arr_name [const_n]
/ / such as:
int arr[10];
Copy the code

Type_t refers to the type of an array element.

Const_n is a constant expression that specifies the size of an array.

When you run the program, the system will warn you that the variable is not initialized. Turn on debugging and you’ll find that the system fills in some meaningless data by default.

Of course, global arrays are initialized to 0 by default;

int arr[10];// 0 0 ... 0
int main(a){
  return 0;
}
Copy the code
Create an instance
/ / 1.
int arr[10];
/ / 2.
int count = 10;
int arr2[count];// Can you create an array like this?
/ / 3.
float arr3[20];// Float array
char ch[10];
Copy the code

Arrays must be created using constants, not variables. C99 supports variable length arrays, but constants are generally sufficient. Likewise, I use const_n for constants, but don’t mistake it for const.

Why is that?

Arrays have always been created using constants because they are too risky to manipulate and access illegal memory.

Initialize the

Initialization, as the name suggests, creates an array while giving some reasonable initial values. Such as:

int arr[10] = { 1.2.3 };// Incomplete initialization
Copy the code

This is incomplete initialization, and the rest of the elements default to 0

int arr2[] = { 1.2.3.4 };// Use the initialization content to specify the size of the array
Copy the code

This is a const_n constant expression that omits an array

The size of the array is specified by the initialization content

What’s the difference between these three?

The first is to initialize an array with a string. The string ends with a \0 flag. It is not the content of a string, but it is almost inherent in the string, so it is initialized as the content of an array. a b c \0

The second is the same as the third because the array element type is a character and the ACSII value of character ‘b’ is 98, which is automatically resolved to a character. a b c

use

Arrays are accessed by subscripts, which by default start at 0. Array elements are accessed by the subscript reference operator [].

int arr[10] = { 1.2.3.4.5.6.7.8.9.10 };
// Array subscripts are 0 to 9 starting from 0
int sz = sizeof(arr) / sizeof(arr[0]);/ / 10
for (int i = 0; i < sz; i++)
{
    printf("%d ", arr[i]);
}
//1 2 3 4 5 6 7 9 10
Copy the code

For sizeof, sizeof(arr), sizeof+ the name of the array, means to calculate the sizeof the entire array, which is 40, and sizeof(arr[0]) is to calculate the sizeof the first element of the array to be 4, which is the number of elements divided by one.

Using the variable sz, you can flexibly change the size of the array without changing the loop conditions.

Conclusion:
  1. Arrays are accessed by subscripts, which start at 0
  2. The size of the array can be computed
Memory storage

Through the printf (” & arr [% d] = % p \ n “, I, & arr [I]); We can see how the array is stored in memory.

It is obvious that arrays are contiguous in memory.

On the right is the hexadecimal memory number. You can see that each element is four bytes apart, and an integer element is exactly four bytes.

So arrays are contiguous in memory, and as the index of the array grows, so does the address, which is why the pointer variable +1 can access the next element of the array.

So what is the nature of an array?

A group of contiguous memory elements of the same type.

2 d array

create
type_t arr_name[const_n][const_n]
//
int arr[3] [5];/ / 3 line five columns
char ch[4] [7];/ / 4 line 5 columns
double arr2[2] [4]/ / 2, line 4 columns
Copy the code

As the code above shows, the syntax for a two-dimensional array is type + array name +[row][column].

As you can see, a two-dimensional array looks like this: three rows and five columns, sort of like a table. Just like a matrix in linear algebra, the definition of a matrix is a list of numbers.

Initialize the
/ / 1.
int arr1[3] [5] = { 1.2.3.4.5.6.7.8.9.10.11 };

/ / 2.
int arr2[3] [5] = {{1.2}, {3.4}, {5.6.7}};Copy the code
  1. The first type of initialization, you fill it in line by line, the first line isOne, two, three, four, fiveThe second row is zero6, 7, 8, 9, 10If the third row is not enough, add zero11 0 0 0 0 0
  2. The second way is to treat each row as a one-dimensional array, and fill it up with zeros if not enough, the first row1 2 0 0 0 And the second line3, 4, 0, 0, 0The third line,5, 6, 7, 0, 0

char ch1[2] [4] = { 'a'.'b' };
char ch2[2] [4] = {{'a'}, {'b'}};char ch3[3] [4] = { "abc"."def"."gh" };
Copy the code

Of course, if you initialize a two-dimensional array with a string, you also need to pay attention to \0.

Line 1: a b c \0; Line 2: d e f \0; Third line: g h \0 0

omit
int arr2[][5] = {{1.2}, {3.4}, {5.6.7}};Copy the code

You can omit rows like this, but you can’t omit columns.

The number of rows can be specified based on the initialization content, but if columns are omitted it creates ambiguity.

Of course, ellipsis must be initialized under the premise, otherwise the row and column do not know, how to allocate space?

use

Of course, a two-dimensional array also uses subscripts to access the contents of the array, again starting at zero. Such as:

So if we’re going to access this two-dimensional array, of course we’re going to loop through the array twice.

Memory storage

Of course, we can also print the address of each element in the same way, for example:

  • We can still see that each element is continuously stored in memory.

In this case, the memory storage of a two-dimensional array is the way you imagine it to be two-dimensional, and if you think of each row as a one-dimensional array, then the memory storage of a two-dimensional array is still one-dimensional. The comparison is shown below:

  • And from this we can understand why, when you initialize a two-dimensional array, you can omit rows and not columns.

I left out the rows, but we know that the columns, you just fill them one by one, as many rows as you can fill.

Understand the way
  • For a two-dimensional array, we can think of each behavior as a one-dimensional array of one element, and each element of that one-dimensional array is in turn a one-dimensional array.

For example, arr[3][5] is a one-dimensional array with three elements, and each element is a one-dimensional array with five elements.

A pointer to a two-dimensional array, plus 1, points to the next row.

It is important to understand how a two-dimensional array can be stored in memory. With this in mind, we can get array elements by iterating through Pointers, such as:

int arr[3] [5] = {{1.2.3}, {4.5.6}, {7.8}};int* p = &arr[0] [0];
for (int i = 0; i < 15; i++)
{
    printf("%d ", *p++);//1 2 3 0 0 4 5 6 0 0 7 8 0 0 0 0 0
}
Copy the code

Array out of bounds problem

define

Arrays are accessed by subscripts, which control the range of arrays. Access before and after the array is illegal access to memory, the array is out of bounds.

//1 2 34 5 -858993460
int arr[5] = { 1.2.3.4.5 };
for (int i = 0; i <= 5; i++)// Cross the line to the sixth
{
    printf("%d ", arr[i]);
}
Copy the code

An out-of-bounds access to a block of memory after the last element. -858993460 is a random value automatically generated by VS2019.

Compilers generally don’t check for out-of-bounds array accesses (VS2019 is too advanced), so we need to consciously check for them. If the compiler prompts an error message like this, then the array is out of bounds:

Array as function arguments

When we write code, we often take arrays as arguments, as in the next two application examples, so we’ll use the bubbling sort implementation as an example. When we write code, we often take arrays as arguments, as in the next two application examples, so we’ll use the bubbling sort implementation as an example.

There are four kinds of sorting algorithms: bubble sort, selection sort, insertion sort and quicksort.

The core idea of bubble sort is to compare two adjacent elements.

  • One bubble sort takes a number and brings it to its final position.
  • If there are NNN elements, a total of N − 1n-1N −1 bubble sort is required, and each sort requires N −1− IN-1 −1− I times to determine the size. As shown in the analysis figure:

void Print(int* arr, int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", *arr++); }}void Sort(int arr[],int sz)//int* arr
// Array parameters are essentially Pointers
{
	//int sz = sizeof(arr) / sizeof(arr[0]); //err// Divide the sizeof the pointer by another value = 4/4 = 1
	for (int i = 0; i < sz - 1; i++)/ / n - 1
	{
		for (int j = 0; j < sz - 1 - i; j++)/ / n - 1 - I times
		{
			if (arr[j] > arr[j + 1])// Target ascending order
			{
				/ / exchange
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp; }}}}int main(a)
{
	int arr[] = { 1.4.6.3.7.9.3.2.8.5 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	// The array name is placed in sizeof alone to represent the entire array
	/ / sorting
	Sort(arr,sz);
	/ / print
	Print(arr,sz);
	return 0;
}
Copy the code
  1. When you define an array as a parameter, it is essentially a pointer.

Void Sort(int arr[],int sz) void Sort(int arr[],int sz)

So sizeof(arr) in Sort() is also the sizeof the pointer arr, so it can only be passed in.

  1. When does the name arr represent the entire array and when does it represent the address of the first element of the array?

    • Representing the entire array:

      When placed inside the sizeof operator, as sizeof(arr); .

      When you write &arr, you represent the entire array, but the address of the first element remains on the surface.

    • Represents the address of the first element:

      All but the preceding two are addresses representing the first element.

Examples of application

I don’t really have time to blog about two examples, so I’ll post a mind map here. Thanks to Sister Li for your support

Array application example 1: checkers

Array application example 2: Minesweeper