Created: 2023-01-11 12:48
Status: #concept
Subject: Programming
Tags: C C Data Type Aggregate Multidimensional Arrays
C Array
It is a derived data structure/type that holds values (also known as elements) of the same type found in different indices.
- we can assign the first element of the array to a pointer like
*p = array
.
An array of Characters in C turns into a C String with the Null Terminator as the last character.
Row-Major Order
- They are stored in Row-Major Order, so the addresses to their elements index positions are separated by the Byte size of its type.
- Multidimensional Arrays are stored in the same fashion.
For Example, here is a One-Dimensional Array named a
:
int a[10]; // (data type) identifier[size]
#define STR_MAX 100
char string[MAX]; // we can also use expressions like Macro Definitions
int a[3] = {1, 2, 3}; // we can also use an Initializer List
int a[] = {1, 2, 3}; // or automatically derive the size
int a[3] = {[1] = 2, [2] = 3}; // we can also use Designators to initialize specific indices
Accessing Elements
We can access arrays in two common ways; with a specific array[index]
or by Dereferencing an array's address with Pointer Arithmetic like *(array + index)
.
Accessing the element of an array beyond its allocated range of Memory Addresses will result to a Segmentation Fault.
Array Subscripting (indexing)
The elements of an array are numbered from
0 to n - 1
, where n
is the array's length.
- Expressions of the form
array[index]
are Lvalues, meaning they can be used the same way as ordinary Variables. - By extension of that, we can also use Characters to index arrays.
a[0] = 1; // to assign values to it
printf("%d\n", a[5]); // to use as a variable in expressions
++a[i]; // to increment or decrement
a['A']; // accesses position 65, the ASCII value of 'A'
Dereferencing Array Addresses
- by extension of that,
k[arr]
is*(k+arr)
, meaning they are commutative. - meanwhile
arr + 1
is equivalent to&arr[1]
. - therefore, the name of the array decays to a pointer to the first element of the array.
int a[10]; // given the address a, offset 10 elements (not bytes) from that address and then dereference the result.
*a = 7; // stores 7 in a[0], *a === a[0], a === &a[0]
*(a+1) = 12; // stores 12 in a[1]
sizeof
Operator Behavior
Using the sizeof Operator helps us determine the number of elements in an array (the array length).
sizeof (array)
returns the size of the array (in Bytes).
sizeof(arr) / sizeof(arr[0])
evaluates to the length of arr
.
// sets the values of an array with unknown size to 0
for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
a[i] = 0;
Copying Array Elements
Since arrays are just chunks of Memory Addresses, we can copy multiple addresses from one place to another with
memcpy
.
void *memcpy(void *dest, const void *src, size_t n)
#define MAX_LEN 3
int a[MAX_LEN] = {1,2,3};
int b[MAX_LEN] = {0,0,0};
memcpy(a, b, sizeof(a)); // copies the elements from b to a
memcpy(a, b, MAX_LEN * sizeof(a[0])); // equivalent
// or we can use a loop
for (int i = 0; i < MAX_LEN; i++) {
a[i] = b[i];
}