C Arrays
Table of Contents
Declaring And Initializing Arrays
An array is a set of values of the same type, stored together in order. Arrays are represented by putting square brackets
after the variable name and the number of array members is enclosed in square brackets.
int sales[100];
The above example declares an array sales
with 100
members, each of which is an int type.
The members of the array are numbered from 0
, so the array sales[100]
will start from member number 0
until member number 99
, and the last member will be numbered 1 less than the length of the array.
If you want to reference a member of an array, you need to use square brackets
after the array name
and put the index number
of that array member in the square brackets. You can also assign a value to the array member at that position by using this method.
sales[0] = 100;
sales[99] = 452;
The above example assigns a value to the first and last position of the array sales
.
int sales[100];
sales[100] = 40;
In the above example, the array sales has only 100
members, so the array element sales[100]
does not exist. However, referencing this array location will not report an error, but will run normally. This would result in the memory area immediately after the array of sales being allocated a value that is actually memory space for other variables, so this would unknowingly change the value of the other variables. This can easily cause errors and is very difficult to detect.
Arrays can also be declared in curly brackets while assigning values to each member.
int a[5] = {1, 2, 3, 4, 7};
int main()
{
int a[5];
a = {1,2,3,4,7};//error
}
Output:
testc.c: In function ‘main’:
testc.c:4:9: error: expected expression before ‘{’ token
4 | a = {1,2,3,4,7};
| ^
In the above code, the compiler will report an error when the array a
is declared and then assigned in curly brackets.
When using curly brace assignment, the value inside the curly brace cannot be more than the length of the array, otherwise the compiler will report an error.
If the value inside the curly brackets is less than the number of members of the array, then the unassigned members are automatically initialized to 0.
int a[5] = {1, 2, 3};
// Equivalent to
int a[5] = {1, 2, 3, 0, 0};
If you want to set every member of the entire array to zero, the easiest way to write it is as follows.
int a[100] = {0};
When an array is initialized, members at a specific index position can be assigned values.
int a[15] = {[2] = 29, [9] = 7, [14] = 48};
In the above example, positions 2
, 9
, and 14
of the array are assigned values, and the values of the other positions are automatically set to 0
.
The assignment of the specified positions can be done out of order, and the following is written in an equivalent way to the above example.
int a[15] = {[9] = 7, [14] = 48, [2] = 29};
Assignment of the specified position and sequential assignment can be used in combination.
int a[15] = {1, [5] = 10, 11, [10] = 20, 21}
In the above example, the positions 0
, 5
, 6
, 10
and 11
of the array are assigned.
The C programming language allows omitting the number of array members inside the square brackets, and then it will automatically determine the length of the array based on the number of values inside the square brackets.
int a[] = {1, 2, 3};
// Equivalent to
int a[3] = {1, 2, 3};
The length of the array a in the above example will be determined as 3 based on the number of values inside the curly brackets.
Array Length
The sizeof
operator returns the length of the entire array in bytes.
int a[] = {22, 37, 3490};
int arrLen = sizeof(a); // 12
In the above example, sizeof
returns the byte length of the array a
as 12
.
Since the data types of the array members are all the same, and the size of each member’s data type is the same, the length of the array divided by the size of the data type gives the number of members of the array.
sizeof(a) / sizeof(a[0])
In the above example, sizeof(a)
is the length in bytes of the whole array, and sizeof(a[0])
is the length in bytes of the first member of the array. The number of members of the array can be calculated by dividing the two length values above.
Note: The data type of the sizeof return value is size_t, so sizeof(a) / sizeof(a[0]) is also of size_t. The placeholder for this type in printf() should be %zd or %zu.
#include <stdio.h>
int main()
{
int x[12];
printf("%zu\n",sizeof(x));
printf("%zu\n",sizeof(int));
printf("%zu\n",sizeof(x)/sizeof(int));
}
Output:
48
4
12
In the above example, sizeof(x)/sizeof(int)
calculates the number of array members to be 12
.
Multidimensional Arrays
The C programming language allows declaring arrays of multiple dimensions. The number of square brackets in an array is the same as the number of dimensions, for example, two square brackets can represent a two-dimensional array.
int board[10][10];
The above example declares a two-dimensional array with 10 elements in the first dimension and 10 elements in the second dimension.
Then the three-dimensional array is declared in three square brackets, and so on.
int c[4][5][6];
When referencing each member of a two-dimensional array, you need to use two square brackets to specify the two dimensions.
board[0][0] = 13;
board[9][9] = 13;
Note: board[0][0] cannot be written as board[0, 0] because 0, 0 is a comma expression that returns the second value, so board[0, 0] is equivalent to board[0].
As with one-dimensional arrays, the first member of each dimension of a multidimensional array is numbered starting from 0.
Multidimensional arrays can also use curly brackets to assign values to all members at once.
int a[2][5] = {
{0, 1, 2, 3, 4},
{5, 6, 7, 8, 9}
};
In the above example, a
is a two-dimensional array, and this assignment is equivalent to writing each member of the first dimension as an array. This way you don’t have to assign a value to each member, and the missing members are automatically set to 0
.
Multidimensional arrays can also specify the position during initialization and assignment.
int a[2][2] = {[0][0] = 1, [1][1] = 2};
In the above example, the values of [0][0]
and [1][1]
positions are specified, and the other positions are automatically set to 0
.
No matter how many dimensions an array has, it is stored linearly inside memory. a[0][0]
is followed by a[0][1]
, a[0][1]
is followed by a[1][0]
, and so on. Thus, multidimensional arrays can also be assigned using single-level curly braces, and the following statement is exactly equivalent to the assignment statement above.
int a[2][2] = {1, 0, 0, 2};
Variable-length Array in C
When declaring an array, the length of the array can be specified by a variable in addition to a constant. This is known as a variable length array
(VLA for short).
int n = x + y;
int arr[n];
In the above example, the array arr
is a variable-length array because its length depends on the value of the variable n
. The compiler cannot determine it in advance, but can only know what n is at runtime.
The basic feature of variable-length arrays is that the length of the array can only be determined at runtime. The advantage of this is that the programmer does not have to specify an arbitrary, indeterminate length for the array at development time; the program can specify an exact length for the array at runtime.
Any array whose length needs to be determined at runtime is a variable-length array.
int i = 10;
int a1[i];
int a2[i + 5];
int a3[i + k];
In the above example, the lengths of all three arrays need to be known at runtime code, and the compiler does not know their lengths, so they are all variable-length arrays.
Variable-length arrays can also be used for multi-dimensional arrays.
int m = 4;
int n = 5;
int c[m][n];
In the above example, c[m][n]
is a two-dimensional variable-length array.
Address of Array in C
An array is a sequence of consecutive stored values of the same type. By obtaining the starting address (the memory address of the first member), the addresses of the other members can be deduced. See the following example.
#include <stdio.h>
int main()
{
int a[5] = {11,22,33,44,55};
int* p;
p =&a[0];
printf("%d\n",*p); //print "11"
}
Output:
11
In the above example, &a[0]
is the memory address of the first member 11
of the array a
, which is also the starting address of the whole array. In turn, from this address (*p)
, the value 11
of the first member can be obtained.
Since the start address of an array is a common operation and &array[0]
is a bit cumbersome to write, C provides a convenient way to write it, where the array name is equivalent to the starting address, i.e., the array name is a pointer to the first member (array[0]).
int a[5] = {11, 22, 33, 44, 55};
int* p = &a[0];
// Equivalent to
int* p = a;
In the above example, &a[0]
and the array name a
are equivalent.
In this case, if you pass an array name into a function, it is equivalent to passing in a pointer variable. Within the function, the entire array is then available through this pointer variable.
The function accepts an array as an argument, and the function prototype can be written as follows.
int sum(int arr[], int len);
Or
int sum(int* arr, int len);
In the above example, passing in an array of integers is the same as passing in a pointer to an integer, and the array symbol []
is interchangeable with the pointer symbol *
. The next example is a summation through an array pointer to a member.
#include <stdio.h>
int sum(int* arr, int len) {
int i;
int total = 0;
for (i = 0; i < len; i++) {
total += arr[i];
}
return total;
}
int main()
{
int a[5] = {11,22,33,44,55};
int sumArray = sum(a,5);
printf("The value of sumArray is %d\n",sumArray);
}
Output:
The value of sumArray is 165
In the above example, the function is passed a pointer called arr
(which is also the name of the array) and the length of the array, which is used to get each member of the array.
The *
and &
operators can also be used for multidimensional arrays.
int a[4][2];
// Get the value of a[0][0]
*(a[0]);
// Equivalent to
**a
In the above example, since a[0]
itself is a pointer to the first member of the second dimensional array, a[0][0]
. Therefore, *(a[0])
takes out the value of a[0][0]
. As for **a
, it is two * operations on a
. The first one takes out a[0]
, and the second one takes out a[0][0]
. Similarly, &a[0][0]
of a two-dimensional array is equivalent to *a
.
Note: The address pointed to by the array name cannot be changed. When an array is declared, the compiler automatically allocates a memory address to the array that is bound to the array name and cannot be changed, and the following code will report an error.
int ints[100];
ints = NULL; // error
In the above example, reassigning the array name and changing the original memory address will report an error.
This also makes it impossible to assign an array name to another array name.
int a[5] = {1, 2, 3, 4, 5};
int b[5] = a; // error
Or
int b[5];
b = a; // error
The above code will change the address of the array b
and will report an error.
Array Operations in C
In the C programming language, array names can be added or subtracted, which is equivalent to moving back and forth between array members, i.e., from the memory address of one member to the memory address of another member. For example, a + 1 returns the address of the next member, and a – 1 returns the address of the previous member.
#include <stdio.h>
int main()
{
int a[5] = {11,22,33,44,55};
for(int i=0;i<5;i++){
printf("%d\n",*(a+i));
}
}
Output:
11
22
33
44
55
In the above example, the array is iterated through pointer moves. each round of the loop for a + i
points to the address of the next member, and *(a + i)
takes out the value of that address, which is equivalent to a[i]
. For the first member of the array, *(a + 0)
(i.e., *a) is equivalent to a[0]
.
Since array names are equivalent to pointers, the following equation always holds.
a[b] == *(a + b)
The above code gives two ways to access array members, one using square brackets a[b]
and the other using the pointer *(a+b)
.
If the pointer variable p
points to a member of an array, then p++
is equivalent to pointing to the next member, and this method is often used to iterate through arrays.
#include <stdio.h>
int main()
{
int a[] = {11, 22, 33, 44, 55, 999};
int* p = a;
while (*p != 999) {
printf("%d\n", *p);
p++;
}
}
Output:
11
22
33
44
55
In the above example, the variable p
is made to point to the next member by p++
.
Note: The address pointed to by the array name cannot be changed, so in the above example, you cannot directly self-increment a. That is, a++ is written incorrectly; you must assign the address of a to the pointer variable p, and then self-increment the variable p.
Iterating through an array is generally implemented by comparing the length of the array, but it can also be done by comparing the start address and the end address of the array.
#include <stdio.h>
int sum(int* start, int* end) {
int total = 0;
while (start < end) {
total += *start;
start++;
}
return total;
}
int main()
{
int arr[5] ={20,10,5,39,4};
printf("%i\n",sum(arr,arr+5));
}
Output:
78
In the above example, arr
is the start address of the array and arr+5
is the end address. As long as the start address is less than the end address, it means that the end of the array has not been reached yet.
By subtracting arrays, you can know how many array members are between two addresses. See the following example to implement a function to calculate the length of an array yourself.
#include <stdio.h>
int main()
{
int arr[5] = {20, 10, 5, 39, 88};
int* p = arr;
while (*p != 88)
p++;
printf("%li\n", p - arr); // 4
}
Output:
4
In the above example, the address of an array member is subtracted from the starting address of the array to find out how many members there are between the current member and the starting address.
When pointers to two members of the same array are subtracted from each other, the distance between them is returned.
int* p = &a[5];
int* q = &a[1];
printf("%d\n", p - q); // 4
printf("%d\n", q - p); // -4
In the above example, the variables p
and q
are pointers to the array position 5
and position 1
, respectively, and their subtraction is equal to 4
or -4
.
Duplicate Elements in an Array in C
Since array names are pointers, copying an array cannot be done simply by copying the array name.
int* a;
int b[3] = {1, 2, 3};
a = b;
The above statement does not copy the array b
to the array a
, but makes a
and b
point to the same array.
The easiest way to copy an array is still to use a loop that copies the array elements one by one.
for (i = 0; i < N; i++)
a[i] = b[i];
In the above example, the assignment of the array is done by copying the members of array b
to array a
one by one.
Another way is to use the memcpy()
function (defined in the header file string.h
) to directly take the memory segment where the array is located and make another copy of it.
memcpy(a, b, sizeof(b));
Passing Arrays as Parameters to Functions in C
Declaring Function with Array as a Parameter
Functions that pass arrays as arguments usually pass the array name and the array length.
int sum_array(int a[], int n) {
// ...
}
int a[] = {3, 5, 7, 3};
int sum = sum_array(a, 4);
The first argument to the sum_array()
function is the array itself, which is the array name
, and the second argument is the length
of the array.
Since the array name is a pointer, if only the array name is passed, the function will only know the address where the array starts, which is why the length of the array needs to be passed in as well.
If the parameters of the function are multidimensional arrays, then the length of the other dimensions need to be written into the function definition, except for the length of the first dimension which can be passed into the function as a parameter.
int sum_array(int a[][4], int n) {
// ...
}
int a[2][4] = {
{1, 2, 3, 4},
{8, 9, 10, 11}
};
int sum = sum_array(a, 2);
The argument to the function sum_array()
is a two-dimensional array. The first argument is the array itself (a[][4]
), which can be written without the length of the first dimension, since it is passed into the function as the second argument, but must be written with the length 4 of the second dimension.
This is because what the function gets internally is just the start address of the array a, and the number of members of the first dimension 2. If you want to calculate the end address of the array correctly, you must also know the length in bytes of each member of the first dimension. Written as int a[][4]
, the compiler knows that each member of the first dimension is itself an array containing 4 integers
, so the length in bytes of each member is 4 * sizeof(int)
.
Variable-length Arrays as Parameters to Functions
When variable-length arrays are used as function parameters, the variables in the variable-length arrays should be written in front of the arrays.
int sum_array(int n, int a[n]) {
// ...
}
int a[] = {3, 5, 7, 3};
int sum = sum_array(4, a);
The array a[n]
is a variable-length array whose length depends on the value of the variable n and can only be known at runtime. Therefore, when the variable n
is used as an argument, the order must precede the variable-length array so that the length of the array a[n]
can be determined at runtime, otherwise an error will be reported.
0 Comments