Arrays - CS2100
Arrays - CS2100
Arrays
An array is a homogeneous collection of data. By homogeneous, it means that all values in the
collection have the same type.
Declaration
Array
Syntax
Uninitialized Declaration
Initialized Declaration
Notes
1. The <size> must be a constant unsigned integer (i.e., constant value or from preprocessor
directive `#!c #define).
2. The number of initial values in { <expr>, <expr>, ... } should match the <size> or
some warnings with undefined behaviour may occur.
3. Each initial values in { <expr>, <expr>, ... } should have the same data type as <data
type> .
It is guaranteed that the elements of the array occupy contiguous memory locations. This will
lead to a very nice retrieval and update instructions later on. Visually, we typically represent the
memory as sequence of box where each box is a memory location the size of the data type and
subscripted (e.g., C[0] , C[1] , ...) with the index.
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 1/30
29/04/2024, 09:49 Arrays - CS2100
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 2/30
29/04/2024, 09:49 Arrays - CS2100
Initialisation
Code
ArrInit.c
Under Initialisation
Under initialisation happens when you are initialising the array with fewer elements that the
size can contain. What will happen is that the rest of the element will be assigned the value
of 0. This is independent of the compiler used (GCC or Clang).
ReplIt
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 3/30
29/04/2024, 09:49 Arrays - CS2100
ArrInit @thisisadiyoga
a.out
1 ELF>�@�@8 @@@@��888
2
3 �
4 �
5 �
6 �
hp
7 �
8 �
9
� � T T T DD P�td ���<< Q�td R�td �
10 �
11 �
12
X X /lib64/ld-linux-x86-
64.so.2 GNU
GNU�D: C� �� Toקkj��� b $:~ �
+"libc.so.6__stack_chk_failputcharprintf__cxa_finalize_
_libc_start_mainGLIBC_2.4GLIBC_2.2.5_ITM_deregisterTMCl
oneTable__gmon_start___ITM_registerTMCloneTable ii
13
L u i V�
14 ��
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 4/30
29/04/2024, 09:49 Arrays - CS2100
After Initialisation
Code
AfterInit.c
1 int e[5];
2 e[5] = {8, 23, 12, -3, 6}; // too late to do this;
3 // compilation error
ReplIt
AfterInit @thisisadiyoga
main
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 5/30
29/04/2024, 09:49 Arrays - CS2100
Syntax
Retrieval
Update
Notes
2. The sub-expression <array name> [ <index> ] retrieves the box at th given index (i.e., the
<index>+1 th element due to 0-indexing).
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 6/30
29/04/2024, 09:49 Arrays - CS2100
Array Summation
ArraySumV1.c
Code
ArraySumV1.c
1 #include <stdio.h>
2 #define MAX 5
3
4 int main(void) {
5 int numbers[MAX];
6 int i, sum = 0;
7
8 printf("Enter %d integers: ", MAX);
9 for (i=0; i<MAX; i++) {
10 scanf("%d", &numbers[i]);
11 }
12
13 for (i=0; i<MAX; i++) {
14 sum += numbers[i];
15 }
16
17 printf("Sum = %d\n", sum);
18 return 0;
19 }
ReplIt
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 7/30
29/04/2024, 09:49 Arrays - CS2100
ArraySumV1 @thisisadiyoga
main
ArraySumV2.c
Code
ArraySumV2.c
1 #include <stdio.h>
2 #define MAX 5
3
4 int main(void) {
5 int numbers[MAX] = {4,12,-3,7,6};
6 int i, sum = 0;
7
8 for (i=0; i<MAX; i++) {
9 sum += numbers[i];
10 }
11
12 printf("Sum = %d\n", sum);
13 return 0;
14 }
ReplIt
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 8/30
29/04/2024, 09:49 Arrays - CS2100
ArraySumV2 @thisisadiyoga
main
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 9/30
29/04/2024, 09:49 Arrays - CS2100
Array Assignment
Code
ArrayAssignment.c
1 #define N 10
2 int source[N] = { 10, 20, 30, 40, 50 };
3 int dest[N];
4 dest = source; // illegal!
5 // We cannot assign to the array (i.e., `<array name> =
<expr>;`)!
ReplIt
ArrayAssignment @thisisadiyoga
main
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 10/30
29/04/2024, 09:49 Arrays - CS2100
So far, the syntax for array retrieval and update is the same as in other programming
languages. What sets C array aparts from other programming languages is that there is a
correspondence between the array and pointers. The correspondence can be summarised as
the following:
Array-Pointer Correspondence
The name of the array corresponds to the address of the first element.
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 11/30
29/04/2024, 09:49 Arrays - CS2100
Proof
Code
ArrPtrCorrespondence.c
ReplIt
ArrPtrCorrespondence @thisisadiyoga
main
This correspondence hides a very important implication. Some of these implications are rather
weird, but they are a logical implication. It is best if you go through the following parts slowly.
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 12/30
29/04/2024, 09:49 Arrays - CS2100
Array Decay
This behaviour of array being treated like a pointer is called array decay. The array decays into a
pointer. The actual of an integer array of size 5 is actually int[5] . However, this information is
lost (hence the decay) whenever we use the array name. The operator sizeof is not technically
a function so when array is used as an argument to this operator, it does not decay. This results
in the difference in behaviour of sizeof(arr) inside the scope the array is declared vs outside
of it (e.g., when passed into parameters).
Retrieval ≈ Dereferencing
Since "The name of the array corresponds to the address of the first element", as a logical
conclusion, the following code:
*arr
Retrieves the first element of the array arr . And we know that the first element is at index 0.
We can incorporate this information as a shift from first address since we also know that "the
elements of the array occupy contiguous memory locations".
*(arr + 0)
Now, we can see how a retrieval of any index can be mapped into a dereferencing operation
with shifts. Given an index idx , we can also retrieve the element via:
*(arr + idx)
Retrieval ≈ Dereferencing
arr[idx] == *(arr + idx)
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 13/30
29/04/2024, 09:49 Arrays - CS2100
Commutativity
Due to the commutativity of the + operator 2, we can have the following weird operation:
Commutativity
1 arr[idx]
2 => *(arr + idx) // by dereferencing
3 => *(idx + arr) // by commutativity
4 => idx[arr]
But remember, idx is an unsigned int and arr is an array. Basically, what we want to say is
that the following code weirdly works.
Code
CommutativeArr.c
ReplIt
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 14/30
29/04/2024, 09:49 Arrays - CS2100
CommutativeArr @thisisadiyoga
main
This simple pointer arithmetic is the reason why array access is so fast. Coupled with the fact
that we do not check whether the index is out of bound, this operation is ultra fast and pretty
much unsafe. The job of checking if the index is out of bound is delegated to you as the
programmer.
In particular, the address and the value of an array variable are always the same. Looking at it
through the box-and-arrow diagram below, the correct visual representation of an array should
the one on the top instead of the bottom.
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 15/30
29/04/2024, 09:49 Arrays - CS2100
In the correct visualisation, there is no memory allocated for the array variable. This is the
reason why there is no address corresponding to the name. In the incorrect visualisation, the
box for a assumes that it has a separate address from a[0] . As such, the name a is treated
by the compiler to be a placeholder for the address of its first element. However, this only
happens in the function where the array is declared. As you will see later when we pass an array
into a function, this does not happen for function parameters.
Although this may seem weird, it actually explains why you cannot assign to an array variable.
How can you when there is no variable to store such value! What you can do instead is to
update the elements of the array as exemplified below:
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 16/30
29/04/2024, 09:49 Arrays - CS2100
ArrayCopy.c
Code
ArrayCopy.c
1 #define N 10
2 int source[N] = { 10, 20, 30, 40, 50 };
3 int dest[N];
4 int i;
5 for (i = 0; i < N; i++) {
6 dest[i] = source[i];
7 }
ReplIt
ArrayCopy @thisisadiyoga
main
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 17/30
29/04/2024, 09:49 Arrays - CS2100
memcpy()
There is another function available in string library (i.e., #include <string.h> ) called memcpy()
that allows us to copy a sequence of memory location into another sequence of memory
location. Since an array is a sequence of memory location, we can also use this to copy an array.
However, this function is outside the scope of the module.
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 18/30
29/04/2024, 09:49 Arrays - CS2100
ArraySumFunction.c
Code
ArraySumFunction.c
1 #include <stdio.h>
2
3 int sumArray(int [], int);
4
5 int main(void) {
6 int val[6] = {44, 9, 17, -4, 22};
7 printf("Sum = %d\n", sumArray(val, 6));
8 return 0;
9 }
10
11 int sumArray(int arr[], int size) {
12 int i, sum=0;
13
14 for (i=0; i<size; i++) {
15 sum += arr[i];
16 }
17 return sum;
18 }
ReplIt
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 19/30
29/04/2024, 09:49 Arrays - CS2100
ArraySumFunction @thisisadiyoga
main
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 20/30
29/04/2024, 09:49 Arrays - CS2100
Array Size
Since C array does not carry information about the size --partly due to the arrays and pointers
correspondence-- most functions working with array have to also accept the size of the array
separately.
Of a particular interest is whether we can actually specify the size as part of the array parameter
itself. To be more precise, can we specify the function definition as the following:
Array Size
Unfortunately, in this case, the compiler will ignore this size. The actual number of elements to
be processed should depend on the variable size .
By the arrays and pointers correspondence above, we can have an alternate definition to the
function using pointers. In fact, you will see that the function body will remain the same while
the function prototype will change.
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 21/30
29/04/2024, 09:49 Arrays - CS2100
ArraySumPointer.c
Code
ArraySumPointer.c
1 #include <stdio.h>
2
3 int sumArray(int*, int);
4
5 int main(void) {
6 int val[6] = {44, 9, 17, -4, 22};
7 printf("Sum = %d\n", sumArray(val, 6));
8 return 0;
9 }
10
11 int sumArray(int *arr, int size) {
12 int i, sum=0;
13
14 for (i=0; i<size; i++) {
15 sum += arr[i];
16 }
17 return sum;
18 }
ReplIt
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 22/30
29/04/2024, 09:49 Arrays - CS2100
ArraySumPointer @thisisadiyoga
main
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 23/30
29/04/2024, 09:49 Arrays - CS2100
Quick Quiz
Question
The sum of square of an array a is defined as the following mathematical summation for an
array of size n:
n
∑ a[i]
i=0
Write the function sum_of_square that accepts a double array and returns the sum of square
of the array.
Code
SumOfSquare.c
ReplIt
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 24/30
29/04/2024, 09:49 Arrays - CS2100
SumOfSquare @thisisadiyoga
main
We have learnt that for a function to modify a variable (e.g., v ) outside the function, the caller
has to pass the address of the variable (e.g., &v ) into the function. What about an array? By the
arrays and pointers correspondence, the value of the address itself is already the address. As
such, there is no need to pass the address explicitly into the function.
Side-Effect
Since passing an array to a function passes the address, whether intended or not, a function can
modify the content of the array it received. This changes can be seen by the caller and hence
constitute a side-effect of the function (the main effect is the return value). You as the
programmer will have to ensure that no changes are made when no changes are supposed to be
made.
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 25/30
29/04/2024, 09:49 Arrays - CS2100
ArrayModify.c
Code
ArrayModify.c
1 #include <stdio.h>
2
3 void modifyArray(float [], int);
4 void printArray(float [], int);
5
6 int main(void) {
7 float num[4] = {3.1, 5.9, -2.1, 8.8};
8 modifyArray(num, 4);
9 printArray(num, 4);
10 return 0;
11 }
12
13 void modifyArray(float arr[], int size) {
14 int i;
15 for (i=0; i<size; i++) {
16 arr[i] *= 2;
17 }
18 }
No Return
Note the absence of return statement in the function modifyArray . The return
statement is unnecessary because the modification is done in-place.
ReplIt
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 26/30
29/04/2024, 09:49 Arrays - CS2100
ArrayModify @thisisadiyoga
main
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 27/30
29/04/2024, 09:49 Arrays - CS2100
Quick Quiz
Question
Write a function abs_array to modify an array such that each element in the array is changed to
its absolute value. You may assume that the array is an array of int .
Code
AbsArray.c
ReplIt
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 28/30
29/04/2024, 09:49 Arrays - CS2100
AbsArray @thisisadiyoga
main
Why Pointers?
Let's look at a possible reason why the name of the array is treated as the pointer to the first
element. Here, we will use a numerical argument. Do not worry too much if you cannot follow
the computation closely.
Consider an array of int with 1 billion element. Since each int has a size of 4 bytes, the total
size of:
Now consider if calling a function actually copies the array instead just the pointer. It means we
now have to be able to store twice the size of the array. That equates to 8GB! Clearly, that's
larger than what most common laptops would have.
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 29/30
29/04/2024, 09:49 Arrays - CS2100
Even worse, imagine if the function then calls another function (or even recursion). The amount
of memory needed is going to be unreasonably large. To remedy this, the convention is to
simply pass the pointer to the first element. As a problematic side-effect, the function may
modify the content of the array. This means that it is now the responsibility of the programmers
to avoid this.
1. This is often called array assignment operation. And in fact, we will often call it that. However, it is
good to mentally separate the operation and keep assignment simple by assuming <var> =
<expr> where <var> is a variable name. On the other hand, update requires the left-hand side to
be an array.
2. We did a bit of hand-waving here, because it is not obvious that + is commutative in the case the
operands are of different type. In arr + idx , the left operand is an address and the right operand
is an integer. On the other hand, for idx + arr , the left operand is a number and the right operand
is an integer.
https://www.comp.nus.edu.sg/~adi-yoga/CS2100/ch05a/ 30/30