<C language> array

1. The creation and initialization of a one-dimensional array.

1.1 Array creation

An array is a collection of elements of the same type.

Declare a one-dimensional array with:

type arrayName[arraySize];

typeis the type of elements in the array, arrayNameis the name of the array, and arraySizeis the size of the array (that is, the number of elements). Note that the size of the array must be a constant, not a variable.

Declare a one-dimensional array instance:

int numbers[5];  //声明一个int型的一维数组,大小为5

char arr3[10];   //声明一个char型的一维数组,大小为10
float arr4[1];    //声明一个float型的一维数组,大小为1
double arr5[20];  //声明一个double型的一维数组,大小为20

//以下代码只有在支持变长数组的情况下才支持。
int count = 10;
int arr2[count];   //err

Note: Before creating an array, 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.

1.2 Array initialization

Array initialization refers to giving some reasonable initial values ​​(initialization) to the contents of the array while creating the array. One-dimensional arrays can be initialized at declaration time , or after declaration through loops or assignment-by-assignment.

Here are some common one-dimensional array initialization methods:

//静态初始化
int arr1[10] = {
    
    1};  			//不完全初始化,第一个元素初始化为1,其余的元素默认初始化为0
int arr2[] = {
    
    1,2,3,4};
int arr3[5] = {
    
    12345}char arr4[3] = {
    
    'a',98, 'c'};
char arr5[] = {
    
    'a','b','c'};
char arr6[] = "abcdef";


// 循环赋值
int numbers[5];
for (int i = 0; i < 5; i++) {
    
    
    numbers[i] = i + 1;
}

//逐个赋值
int numbers[5];
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;
numbers[3] = 4;
numbers[4] = 5;

If no initial value is provided, the elements of the array are automatically initialized according to the type of the array. For example, for integer arrays, elements will be initialized to 0; for character arrays, elements will be initialized to a null character ('\0').

1.3 Use of one-dimensional arrays

1. Accessing array elements : You can use the index to access a specific element in the array, the index starts from 0, and the maximum index is the size of the array minus 1 . Array elements can be accessed using the following syntax:

Example: to access numbersthe third element in an array:

int x = numbers[2];

2. Modify the array elements :

For example: modify numbersthe first element in the array to be 10:

numbers[0] = 10;

3. Traverse the array :

You can use a loop structure (such as fora loop) to traverse the entire array, accessing each element to perform operations.

For example: iterating over an array numbersand printing out each element:

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

4. Pass the array to the function:

Arrays can be passed as arguments to functions, either by passing a pointer to the array or using the array as a formal parameter.

For example: the function accepts an integer array as a parameter and calculates the sum of all elements in the array:

int calculateSum(int arr[], int size) {
    
    
    int sum = 0;
    for (int i = 0; i < size; i++) {
    
    
        sum += arr[i];
    }
    return sum;
}

Call the function and pass the array:

int result = calculateSum(numbers, arraySize);

Note: The size of the array can be calculated by

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

1.4 Storage of one-dimensional arrays in memory

One-dimensional arrays are stored continuously in memory, and they are stored sequentially in a continuous memory space.

When you declare a one-dimensional array and allocate memory for it, the computer allocates a contiguous piece of memory for the array to store its elements. The size of the array determines how much memory space needs to be allocated, and the size of each element depends on the data type of the array elements.

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

The output is as follows:

&arr[0] = 000000000061FDF0
&arr[1] = 000000000061FDF4
&arr[2] = 000000000061FDF8
&arr[3] = 000000000061FDFC
&arr[4] = 000000000061FE00
&arr[5] = 000000000061FE04
&arr[6] = 000000000061FE08
&arr[7] = 000000000061FE0C
&arr[8] = 000000000061FE10
&arr[9] = 000000000061FE14

It can be seen that because it is an int type, it increments by 4 bytes each time

2. Creation and initialization of two-dimensional array

A two-dimensional array is an array of multiple one-dimensional arrays. It can be seen as a table or matrix, with the concept of rows and columns.

2.1 Creation of two-dimensional array

//数组创建
int arr[3][4];  //三行四列的整型二维数组
char arr[3][5];  //三行五列的字符型二维数组
double arr[2][4];   //二行四列的double型二维数组

2.2 Initialization of two-dimensional array

1. Initialize by row:

Initialize a two-dimensional array of integers with 3 rows and 4 columns:

int matrix[3][4] = {
    
    {
    
    1, 2, 3, 4}, {
    
    5, 6, 7, 8}, {
    
    9, 10, 11, 12}};

In this example, matrixit is a two-dimensional array of integers containing 3 rows and 4 columns, and the value of each element is initialized by row.

2. Use loop initialization:

You can use nested loops to assign values ​​to each element of a two-dimensional array.

For example, to initialize a two-dimensional integer array containing 3 rows and 4 columns, each element is assigned a value of 0:

int matrix[3][4];
for (int i = 0; i < 3; i++) {
    
    
    for (int j = 0; j < 4; j++) {
    
    
        matrix[i][j] = 0;
    }
}

In this example, matrixeach element of is assigned a value through nested loops.

3. Partial initialization:

You can initialize only part of the elements of the two-dimensional array, and the rest of the elements will be automatically initialized to default values ​​(such as 0).

For example, to initialize a two-dimensional integer array containing 3 rows and 4 columns, only the first two rows are initialized:

int matrix[3][4] = {
    
    {
    
    1, 2, 3, 4}, {
    
    5, 6, 7, 8}};

In this example, the elements of the first two rows are initialized, and the elements of the third row will be automatically initialized to 0.

Note: If the two-dimensional array is initialized, the row can be omitted, but the column cannot be omitted

Here is an example:

int matrix[][3] = {
    
    {
    
    1, 2, 3}, {
    
    4, 5, 6}, {
    
    7, 8, 9}};

In this example, we omit the number of rows, but specify 3 columns per row. The compiler will automatically calculate the number of rows to be 3 based on the provided initialization value, and allocate the corresponding memory space.

In addition, some elements can also be initialized:

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

In this example, we only provided initialization values ​​for two rows, without specifying the number of rows. The compiler will automatically calculate the number of rows to be 2 based on the provided initialization value, and allocate the corresponding memory space. The third line will be automatically initialized to a default value (usually 0).

2.3 Use of two-dimensional arrays

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

1. Access array elements:

For example, to access matrixelements in a two-dimensional array named :

int matrix[3][4];
matrix[1][2] = 42;  // 将第二行第三列的元素赋值为42

2. Traverse the array:

Nested loops can be used to iterate over all elements of a two-dimensional array. The outer loop is used to iterate over the rows, and the inner loop is used to iterate over the columns.

For example, to iterate over a matrixtwo-dimensional array named and print all elements:

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

3. Multidimensional arrays as function parameters:

You can pass two-dimensional arrays as arguments to functions. When the function is declared, the number of columns of the array needs to be specified, and the number of rows can be omitted.

For example, define a function that accepts a two-dimensional integer array as an argument:

void printMatrix(int matrix[][4], int numRows) {
    
    
    for (int i = 0; i < numRows; i++) {
    
    
        for (int j = 0; j < 4; j++) {
    
    
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

2.4 Storage of two-dimensional arrays in memory

A two-dimensional array stores its elements in a contiguous manner in memory. The C language uses row-major order to store two-dimensional arrays, that is, adjacent elements are arranged in memory in rows.

int matrix[3][4] = {
    
    
    {
    
    1, 2, 3, 4},
    {
    
    5, 6, 7, 8},
    {
    
    9, 10, 11, 12}
};

In memory, this two-dimensional array will be stored as a contiguous memory block, and each element is arranged in rows, as follows:

[1][2][3][4][5][6][7][8][9][10][11][12]

From a memory point of view, a two-dimensional array matrixis actually one-dimensional, but specific elements can be easily accessed through a combination of row and column indices.

When you use matrix[i][j]to access an array element, the compiler will calculate the correct memory address based on the type of the array and the value of the index. For the above example, matrix[1][2]when accessing , the compiler will calculate the memory address as &matrix[1][2]and return the corresponding value.

Note that both row and column indices start from 0. For two-dimensional arrays matrix, row indices range from 0 to 2, and column indices range from 0 to 3.

Like 1D array, here we try to print 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;
}

Output result:

&arr[0][0] = 000000000061FDE0
&arr[0][1] = 000000000061FDE4
&arr[0][2] = 000000000061FDE8
&arr[0][3] = 000000000061FDEC
&arr[1][0] = 000000000061FDF0
&arr[1][1] = 000000000061FDF4
&arr[1][2] = 000000000061FDF8
&arr[1][3] = 000000000061FDFC
&arr[2][0] = 000000000061FE00
&arr[2][1] = 000000000061FE04
&arr[2][2] = 000000000061FE08
&arr[2][3] = 000000000061FE0C

3. Array out of bounds

When accessing an array, array out-of-bounds refers to the use of an index value outside the valid index range of the array. In the C language, the index of the array starts from 0, and the maximum index is the length of the array minus 1. Array out-of-bounds leads to undefined behavior, which may cause the following problems:

1. Read uninitialized memory:

When attempting to read an element outside the bounds of an array, the memory location accessed may not belong to the array. This means that what is actually read is uninitialized memory content whose value is undefined. This may cause the program to produce erroneous results or unpredictable behavior.

int arr[5] = {
    
    1, 2, 3, 4, 5};
int value = arr[10];  // 越界访问

In the above example, arrthe length of the array is 5, but we try to access the element by index 10, which is outside the valid index range of the array and results in undefined behavior.

2. Write illegal memory:

When you try to write data at a location outside the bounds of the array, you actually modify a location in memory that doesn't belong to the array. This could cause other variables or data to be modified, or cause the program to crash.

int arr[3] = {
    
    1, 2, 3};
arr[5] = 10;  // 越界写入

In the above example, arrthe length of the array is 3, but we try to write an element by index 5, which is outside the valid index range of the array, which will result in writing to an illegal memory location, destroying the integrity of the memory.

3. Buffer overflow:

Using an array to store strings or other data and attempting to write data beyond the bounds of the array may result in a buffer overflow. This may corrupt adjacent memory data or cause security holes such as buffer overflow attacks.

char str[5] = "Hello";
str[5] = '!';  // 越界写入

In the above example, strthe length of the array is 5, but we try to write a character at the 6th position '!', which is outside the valid index range of the array, and may destroy data in adjacent memory or cause a missing string terminator \0.

It is very important to avoid array out-of-bounds problems. Make sure to use valid indices when accessing arrays, and be careful with boundary conditions when iterating arrays. The C language itself does not perform an out-of-bounds check for array subscripts, and the compiler may not necessarily report an error, but the fact that the compiler does not report an error does not mean that the program is correct. Therefore, when programmers write code, it is best to do the out-of-bounds check by themselves.

4. Arrays as function parameters

Often when we write code, we pass an array as a parameter to a function, for example: I want to implement a bubble sort function.

//方法1:
#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);//是否可以正常排序?
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    
    
        printf("%d ", arr[i]);
    }
    return 0;
}

insert image description here

After debugging sz=1, it is very strange, sizeof(arr) / sizeof(arr[0])why is it calculated as 1? This is because in the function parameters, the array will degenerate into a pointer, and sizeofthe size of the array cannot be obtained correctly through the operator. Inside the function, the parameter arris actually a pointer to an integer.

To get the size of the array inside the function, you need to pass the length of the array as an additional parameter, or add a specific marker after the last element of the array to indicate the end of the array.

So the correct way is as follows:

void bubble_sort(int arr[], int size) {
    
    
    int sz = size;
    // 其他代码不变
}

int main() {
    
    
    int arr[] = {
    
    3, 1, 7, 5, 8, 9, 0, 2, 4, 6};
    int size = sizeof(arr) / sizeof(arr[0]);
    bubble_sort(arr, size);
    // 其他代码不变
}

4.1 What is the array name?

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

in 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, then:

int arr[10] = {
    
    0};
printf("%d\n", sizeof(arr));

Why is the output result: 40?

Replenish:

  1. sizeof(数组名), calculate the size of the entire array, sizeofput an array name inside alone, and the array name represents the entire array.
  2. &Array name, the address of the array is taken out. &Array name, the array name represents the entire array.

Except for the two cases 1 and 2, all array names represent the address of the first element of the array.

In addition, it should be noted that the array name itself is a constant pointer and cannot be modified. You cannot use assignment operations on array names, eg arr = some_other_array;is illegal.

Guess you like

Origin blog.csdn.net/ikun66666/article/details/131353629