Do you really understand "array" in C language? (Beginner Level)

⭐ preface

This paper will introduce the array in C language;

Through arrays, we can more easily store and access these elements.

In addition, arrays can also be combined with pointers to form array pointers or pointer arrays. (this is the focus, and a separate note will be made later)

This chapter will focus on one-dimensional arrays and two-dimensional arrays.

Let's get it!

1. Introduction to array

Let's first understand the array as a whole, and then understand it in depth!

🎃 Sequential storage

Sequential storage structure refers to the sequential storage of data with a section of storage units with continuous addresses.

As shown in the figure, each blue square corresponds to a data in the array:

There are data types, such as 32-bit integer int, single precision floating-point float, double precision floating-point double, character char, 64 bit integer long long, 16 bit short, etc.

🎃 Storage mode

In the programming language, the sequential storage structure is realized by one-dimensional array;

In C language, the first data element is stored in the position with subscript 0, the second data element is stored in the position with subscript 1, and so on.

In C language, array is defined as follows:

int arr[7];

We can also initialize the array elements as follows:

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

Since the compiler can know how many data elements there are through the following initialization list, the numbers in brackets can be omitted as follows:

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

Of course, we can also define a large array, but only initialize a few elements:

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

🎃 Length and capacity

The length of the array refers to the current number of elements in the array, and the capacity of the array refers to the maximum number of elements that can be stored in the array.

If the array element is larger than the maximum storage range, it is not allowed in the program, which may cause unexpected problems and need to be avoided in implementation.

As shown in the figure above, the length of the array is 5, that is, the red part; The capacity is 8, i.e. red plus blue.

For example, the following array:

int arr[8] = {9, 8, 7, 6, 5};

🎃 Index of array

The [] operator can be used to complete the element index in the array, for example:

int a[7] = {5, 2, 0, 1, 3, 1, 4};
int b = a[0];    // 5 
int c = a[6];    // 4
int d = a[7];    // error

In this code, a[0] represents the first element of the array, and a[6] represents the last element of the array.

a[7] is illegal because there are seven array elements, and this call indexes the eighth element. If the program calls like this, it may cause a location error.

This error call is generally called array subscript out of bounds.

The above profile is from brother hero LeetCode zero basis guide one dimensional array

Next, officially enter the learning of array!

2. Creation and initialization of one-dimensional array

How to create an array:

type_t   arr_name[const_n];

//type_t is the element type of the index group
//const_n is a constant expression that specifies the size of the array

For example:

int arr1[5];
char arr2[10];
float arr3[8];
double arr4[20];

All the above creation forms conform to the creation syntax of array.

🐱 ‍ 🏍 Note: when creating an array, a constant must be given in [], and variables cannot be used.

For example:

int main()
{
	int i = 20;

	int arr[i];

	return 0;
}

Operation results:

🌳 Initialization of array

Array initialization means that some reasonable initial values (initialization) are given to the contents of the array while creating the array.

If you really can't think of an initial value, you can directly assign it to 0 during initialization;

Code example:

int main()
{
	int arr1[5] = { 1,2,3,4,5 };
    
	int arr2[5] = { 0 };//If only one 0 is passed, all the contents of the array will be initialized to 0
    
	char arr3[3] = { 'a',98, 'c' };//char variable directly stores numbers and puts ASCII characters corresponding to numbers
    
	char arr4[3] = { 0 };//Initialize the contents of the array to '\ 0'. Note that this is not the character 0
    
	return 0;
}

🐱 ‍ 👓 Let's take a look through debugging:

If the array is not fully initialized, the rest of the array will be automatically initialized to 0, and the char type will be automatically initialized to \ 0

Code example:

int main()
{
	int arr1[10] = { 1,2,3,4,5 };
	char arr2[10] = { 'a',98, 'c' };
	return 0;
}

Mode result:

When creating an array, if you want to not specify the determined size of the array, you must initialize it.

The number of elements of the array is determined according to the initialization content.

📄 Code example:

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	char arr2[] = { 'a','b','c' };
	char arr3[] = "abc";
    
	return 0;
}

Commissioning results:

In the above code, the arr1 array does not have a specified size, so it will be automatically allocated five int size spaces in initialization;

Similarly, arr2 and arr3 are the same, but the sizes of arr2 and arr3 are different.

This involves the initialization of character array.

🟠 Initialization of character array

When we want to initialize a character array, we can store each character separately in the form of {','};

You can also store a string directly in the form of "".

The two types are different:

int main()
{
	char arr1[] = { 'a','b','c' };

	char arr2[] = "abc";

	return 0;
}

Commissioning results:

It can be seen from the monitoring that the form of directly storing a string is actually to store each character of the string separately in the character array;

However, it is necessary to store one more \ 0 at the end of the string than to store the characters alone, resulting in 1 more space for storing the string than for storing the characters directly

For the difference between character array and string array, please refer to a blog I wrote earlier: Deep understanding of character arrays and string arrays

🌳 Storage of one-dimensional array in memory

One dimensional array elements are stored continuously in memory. With the increase of array subscript, the address changes from low to high;

We get the address of each array by & (taking the address symbol)

Code example:

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

Operation results:

✨ Resolution:

The addresses are hexadecimal. When converted to hexadecimal, it can be found that the difference between each element of the array is 4, which is the size of the int variable;
 
Therefore, it can be found that one-dimensional array elements are stored continuously in memory, and the address is increasing.
 
Similarly, arrays of char type are stored continuously, but the size of char type is 1, so the difference between each element is 1;
 
The integer array is stored in memory as follows:

🌳 Use of one-dimensional arrays

We can access and use one-dimensional arrays by subscript;

📄 Code example:

int main()
{
	int arr[10] = { 0 };//Incomplete initialization of array
	
	
	int sz = sizeof(arr) / sizeof(arr[0]);//Count the number of elements in the array

	//Assign a value to the contents of the array. The array is accessed by subscript, which starts from 0.

	int i = 0;//Subscript
	for (i = 0; i < 10; i++)
	{
		arr[i] = i;
	}

	//Output the contents of the array
	for (i = 0; i < 10; ++i)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

Operation results:

Because arrays are stored continuously in memory, we can also access and modify array elements through pointers;

Generally, the array name arr represents the first element address of the array. For the first element address of the array + 1, you can skip the first element address to find the second element address, and then find the corresponding array content through the dereference operator *.

📄 Modification code:

int main()
{
	int arr[10] = { 0 };//Incomplete initialization of array
	
	
	int sz = sizeof(arr) / sizeof(arr[0]);//Count the number of elements in the array

	//Assign a value to the contents of the array. The array is accessed by subscript, which starts from 0.

	int i = 0;//Subscript
	for (i = 0; i < 10; i++)//An array of size 10 with subscripts 0-9
	{
		*(arr+i) = i;//Find the corresponding element through the pointer
	}

	//Output the contents of the array
	for (i = 0; i < 10; ++i)
	{
		printf("%d ", *(arr + i));
	}
	return 0;
}

Operation results:

Summary:

Arrays are accessed using subscripts that start at 0.
 
The size of the array can be calculated.

✨ Array size calculation method:

int arr[10];
int sz = sizeof(arr)/sizeof(arr[0]);

What is the array name of a one-dimensional array

Generally, the name of a one-dimensional array is the address of the first element of the array, except for two cases:

Sizeof (array name): in this case, the array name is the array name of the entire array, and sizeof calculates the size of the entire array. If you want to calculate the size of an element of the array, you need to add a subscript. For example, sizeof(arr[0]) calculates the size of the first array element of arr
 
&Array name. In this case, the array name is also the array name of the whole array. If & array name + 1, the whole array will be skipped instead of one element of the array.

Code example:

int main()
{
	int arr[10] = { 0 };

	int sz = sizeof(arr) / sizeof(arr[0]);

	printf("%d\n", sz);

	printf("%p\n", &arr);

	printf("%p\n", &arr + 1);

	return 0;
}

Operation results:

It can be seen from the above program that sizeof(arr) calculates the size of the entire array 40;

sizeof(arr[0]) calculates that the size of the first element of the array is 4. Divide the two to get the number of elements of the array 10;

&Arr gets the address of the entire array. For + 1, the entire array is skipped. The skipped size is the size of the array 40;

3. Two dimensional array

🌳 Creation of two-dimensional array

Two dimensional array adds the concepts of row and column on the basis of one-dimensional array. The creation syntax is as follows:

type_t   arr_name   [const_line][const_column];

//type_t is the element type of the index group
//arr_name is the name of the array
//const_ The number of elements per line of the line array
//const_column array the number of elements per column

use

//Array initialization
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};

🌳 Initialization of two-dimensional array

When initializing a two-dimensional array, rows can be omitted, but columns cannot be omitted. If the shaping two-dimensional array is not fully initialized, it will be automatically initialized to 0;

Code example:

int main()
{

	int arr1[3][4] = { 1,2,3,4 };

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

	int arr3[][4] = { {2,3},{4,5} };

	return 0;
}

Commissioning results:

arr1 array:

arr2 array:

arr3 array:

✨ Conclusion:

It can be seen that if {} is not used for initialization, such as arr1, the compiler will fill the first line by default, then the second line, and finally initialize the remaining uninitialized elements to 0;
 
If {} such as arr2 is added, the compiler will initialize according to our requirements, and the last uninitialized element will also be initialized to 0;
 
After omitting a line, the compiler calculates the size of the line itself.

🌳 Storage of two-dimensional array in memory

Like one-dimensional arrays, two-dimensional arrays are also stored continuously in memory;

Code example:

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;
}

Operation results:

Through the results, we can analyze that in fact, two-dimensional arrays are also continuously stored in memory.

🌳 Use of two-dimensional arrays

Like one-dimensional arrays, we can access and use two-dimensional arrays through subscripts and pointers.

Access via subscript:

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 * 4 + j;
		}
	}

	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}

Operation results:

Access via pointer:

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 * 4 + j;
		}
	}

	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("%d ", *(*(arr + i) + j));
		}
		printf("\n");
	}

	return 0;
}

Operation results:

In a two-dimensional array, the array name is the address of the first row;

Array name + 1 skips the first row and points to the elements of the second row

Code example:

int main()
{
	int arr[3][4] = { 0 };

	printf("%p\n", arr);

	printf("%p\n", arr+1);

	printf("%p\n", *(arr + 1)+1);

	return 0;
}

Operation results:

4. Meaning of array name

Code example:

int main()
{
    int arr[10] = { 1,2,3,4,5 };

    printf("%p\n", arr);
    printf("%p\n", &arr[0]);
    printf("%d\n", *arr);
 
    return 0;
}

Operation results:

Conclusion:

The array name is the address of the first element of the array. (with two exceptions)

If the array name is the address of the first element:

int main()
{
	int arr[10] = { 0 };

	printf("%d\n", sizeof(arr));

	return 0;
}

Operation results:

Why is the output: 40?

✨ Resolution:

sizeof (array name), calculate the size of the entire array. sizeof has a separate array name inside, and the array name represents the entire array.
 
&Array name. The address of the array is taken out& Array name, which represents the entire array.
 
Except for the above two cases where sizeof (array name) and & array name represent the address of the whole array, the array name represents the address of the first element of the array.
 
Important: if sizeof (array name + 0), it does not represent the address of the whole array, but the address of the first element of the array, because the array name must be placed in sizeof alone to represent the address of the whole array.

🌳 Design of bubble sorting function

Let's start with an error code:

//Method 1
void bubble_sort(int arr[])
{
    int sz = sizeof(arr) / sizeof(arr[0]);//Is that right?
    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);//Can I sort normally?
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

When we run, we will report an error!
 
If something goes wrong, let's find the problem. After debugging, we can see the bubble_ sz inside the sort function is 1.
 
When an array is used as a function parameter, does it not pass the of the entire array?
 
When an array passes parameters, it actually just passes the address of the first element of the array.
 
Therefore, even if the function parameters are written in the form of an array: int arr [] represents a pointer: int *arr.
 
Then, the sizeof(arr) result inside the function is 4.

If method 1 is wrong, how to design it?

📃 Code example:

void bubble_sort(int arr[], int sz)
{
    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]);//First calculate the size of the array in the main function

    bubble_sort(arr, sz);

    for (int i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }

    return 0;
}

Operation results:

In fact, for the principle and implementation method of bubble sorting, please refer to a blog I wrote earlier: Deep understanding of bubble sorting algorithm

5. Conclusion

This concludes the summary of arrays!

Then we can use the array to write a few small games, such as Sanzi and Minesweeper

The implementation principle and idea of Sanzi chess can also be seen in a blog I wrote earlier: Upgraded version of Sanzi chess game (chess board interface beautification + animation demonstration)

As long as you understand it well and practice more, there is nothing you can't do!

I will also send out the exercises on arrays after subsequent analysis!

🌟 The more you know, the more you don't know. I'll see you next time!

Tags: function C++ Algorithm C array

Posted by Mr_J on Thu, 09 Dec 2021 13:52:03 +1030