Overview
In programming, arrays are a fundamental type of data structure. When it comes to Solidity, they differ significantly from what you may be accustomed to in other programming languages.
In this article, we'll look at how to use both fixed and dynamic arrays in Solidity. We will examine the declaration, initialization, and manipulation of Solidity arrays as well as some of the key distinctions between Solidity arrays and those found in other programming languages. This lesson will arm you with the skills you need to use arrays successfully in your smart contracts, regardless of your level of Solidity experience.
What Is an Array?
An array in Solidity is a group of data of the same kind that are kept in orderly list form. There are two main ways to declare an array in Solidity. They are as follows:
- Fixed Arrays
- Dynamic Arrays
Fixed Arrays
In a fixed array, the size of the array is determined during its declaration. This size cannot be modified after the array has been created. This means that if you create an array to take in 5 values (i.e., the size of the array is 5), you cannot have 4 items or 6 items in the array. It has to be exactly five items.
Declaring or Initializing Fixed Arrays
Fixed arrays are declared or initialized in the following format: dataType = [arraySize in numbers] arrayName;
Here are a few examples:
uint8[3] scores; //AN ARRAY OF 3 UNSIGNED 8-BIT INTEGERS
string[6] names; //AN ARRAY OF 6 STRINGS
bool[2] isJumping; //AN ARRAY OF TWO BOOLEANS
To add items to the initialized arrays, the simple format of arrayName[index] = value;
is used.
NOTE: Indexes are used to access the values of arrays. Think of indexes as positions. The first index of an array in Solidity is 0.
As an example, consider the following:
scores[0] = 10; //ASSIGNS THE VALUE 10 TO THE FIRST ELEMENT OF THE ARRAY
scores[1] = 25; //ASSIGNS THE VALUE 25 TO THE SECOND ELEMENT OF THE ARRAY
scores[2] = 15; //ASSIGNS THE VALUE 15 TO THE THIRD ELEMENT OF THE ARRAY
In the above example, 3 values were added to the array, scores
. Another way to assign values to fixed arrays is to add the values at the point of initialization. By making use of the above scores
array, this is demonstrated below:
uint8[3] scores = [10, 25, 15];
What Makes Both Methods Different?
The first method of adding items to an array actually serves more than one purpose. It can be used to modify the values of the array as well. The second method simply serves as a way of adding initial values to the array. These values can still be modified by using the first method. Any of the methods can be used, depending on your use case.
NOTE: The values inside the arrays can be modified. This is not the same for the size of the array. It is constant.
When To Use Fixed Arrays.
Fixed arrays are to be used when the values of the array are already known and are constant. Only use them when you know the exact size of the array in advance.
Dynamic Arrays
As opposed to fixed arrays, dynamic arrays are not restricted to a particular size at compile time. The sizes of dynamic arrays can be changed at runtime without running into any issues. The sizes can easily be modified by making use of the push
and pop
methods. These methods cannot be used with fixed arrays.
Declaring Dynamic Arrays
To initialize a dynamic array, the data type of the array needs to be specified, but not the size of the array. The size of the dynamic array is stored as a separate variable. This is because the size of the array can grow or shrink when needed, during runtime.
When a dynamic array is created, Solidity allocates a block of memory to store the elements of the array, and also allocates a separate variable to store the size of the array. The size of the array is stored as a separate variable, rather than as part of the array itself.
To initialize a dynamic array, use the following format dataType[] arrayName;
. Here is an example for reference:
string[] fruits; //CREATES AN ARRAY OF STRINGS
Modifying Dynamic Arrays
As mentioned earlier, dynamic arrays can be increased or decreased in size by making use of the push
and pop
methods. Let us see how they work.
push
Method:
This method is used to add elements to an array, which ultimately increases its size. The push
method takes in one parameter - the value that will be added to the array. This method can only be used to add items to the end of an array. Here is how it works:
fruits.push("Apples"); //ADDS THE VALUE, "Apples" TO THE END OF THE ARRAY
fruits.push("Bananas"); //ADDS THE VALUE, "Bananas" TO THE END OF THE ARRAY
//RESULTING ARRAY
fruits = ["Apples", "Bananas"];
Since the push
method only adds items to the end of the array, a way has to be devised to modify values at specific positions. This is done by simply accessing the array by an index and giving it a value. Here is an example:
fruits[2] = "Pineapples"; //ADDS "Pineapples" TO THE THIRD POSITION OF THE ARRAY
fruits[0] = "Lemons"; //CHANGES THE FIRST VALUE OF THE ARRAY TO "Lemons"
//RESULTING ARRAY
fruits = ["Lemons", "Bananas","Pineapples"];
pop
Method
This method is used to remove the last item of an array, which causes the array to reduce in size. Unlike the push
method, it does not take any parameter. This makes sense because it only removes the last item of an array. Using the above fruits
array, let us consider the following example:
fruits.pop(); //REMOVES THE LAST VALUE FROM THE FRUITS ARRAY
//RESULTING ARRAY
fruits = ["Lemons", "Bananas"];
fruits.pop() //REMOVES THE LAST VALUE FROM THE FRUITS ARRAY
//RESULTING ARRAY
fruits = ["Lemons"];
Just like with the push
method, the pop
method doesn’t give the flexibility to remove values at specific positions. This can be done with the delete
keyword.
delete
Keyword
The delete
keyword is used to remove items from an array at a specified index or position. It can also be used to delete an entire array. Consider the following examples:
//DELETING ENTIRE ARRAY
string fruits[] = ["Lemons", "Bananas","Pineapples"]; //CREATE DYNAMIC ARRAY OF STRINGS
delete fruits; //DELETES ALL ITEMS FROM THE ARRAY
//DELETING ONE PART OF THE ARRAY
string fruits[] = ["Lemons", "Bananas","Pineapples"]; //CREATE DYNAMIC ARRAY OF STRINGS
delete fruits[1]; //DELETES THE SECOND ITEM IN THE ARRAY(INDEX 1)
//RESULTING ARRAY
fruits = ["Lemons", "Pineapples"];
Things To Note About The delete
Keyword
- Although the delete keyword reduces the size of the array by removing an item from it, it does not clear out the memory used by the item. This means that when you try to access the element by using the index, it will return its original value i.e.
fruits[1];
will return"Bananas"
which was previously deleted. The deleted item will continue to retain its memory unless it is overwritten. - Another thing to note is that the
delete
keyword only works on a dynamic array. Using it on a fixed array will yield some errors. 3.While using the delete keyword can get rid of items or arrays that we want, it can also cause fragmentation in the memory heap, leading to reduced performance and increased gas fees. The memory heap is a block of memory that is used to store data structures in Solidity. Fragmentation of the memory heap refers to gaps or holes in the heap as a result of the deletion of data structures such as arrays. It leads to increased gas fees and reduced performance because Solidity has to search for available blocks of memory when allocating new data structures.
Initializing Arrays With The public
Access Modifier
In Solidity, declaring a variable or a function as public
means that it should be visible and callable from outside the contract it was defined in. Using the public
access modifier automatically creates a getter function for the variable that can be called from outside the contract to retrieve the value of the variable.
When you declare an array with the public
access modifier, it looks like this: uint[] public a;
. This type of declaration automatically creates a dynamic array of unsigned integers stored in memory and also creates a public getter function for the array that can be called from outside the contract to retrieve the value of the array.
Initializing an array with uint[] a;
will create a dynamic array of unsigned integers but will not create a getter function for the array because state variables in solidity are private
by default unless specified otherwise.
Differences Between Arrays In Solidity and Other Programming Languages.
- Solidity arrays are stored in memory: In Solidity, arrays are stored in memory, not on the stack like in some other languages. This means that the memory layout of an array in Solidity is different from the memory layout of an array in a language like C or C++. In particular, the elements of an array in Solidity are not necessarily stored consecutively in memory, as they are in C or C++.
- Solidity arrays are not always contiguous: In Solidity, the elements of an array may not always be stored consecutively in memory. For example, if you have a dynamic array of structs, the structs may be scattered throughout memory, with pointers to each struct stored in the dynamic array. This is because Solidity does not guarantee that the elements of an array will be stored consecutively in memory, as it does in languages like C or C++.
- Solidity arrays are not always indexed by integers: In Solidity, you can create arrays that are indexed by any type of data, not just integers. For example, you can create an array of strings indexed by bytes32, or a mapping from uint to bool. This is different from languages like C or C++, which only allow arrays to be indexed by integers.
Conclusion.
In this article, we have been able to see the different types of arrays in Solidity and thing to consider when making use of them. We have also seen how arrays in Solidity differ from arrays in other programming languages. Feel free to like and comment your opinion or suggestions below. If you need any help, reach out via Twitter.