Introduction
We are going to go over the arrays of C today. They are a really important concept of any programming language, so do pay attention. After that we will look at “strings“. There is really no string data type in C, but there is a way to work with sequences of characters as we will see.
So without further ado, let’s jump right into it!
Arrays
Definition
Array is an important data type. You can imagine it as a collection of data which share the same data type. It’s got a fixed size that cannot be changed once initialized.
For example, to define an array holding numbers 1 to 5 you would write:
int numbers[5] = {1, 2, 3, 4, 5};You first enter the type of data you want to hold, then the identifier followed by brackets [] with the specified size inside.
You can also define the array without specifying its size. The size will be computed statically during the translation. For example, character array of size 3:
char three[] = {'h', 'e', 'y'};Accessing array
To get an element from the array, we use a special number called the index, which we once again use inside the [] operator. Index with value 0 signifies the first element of an array. This is usual across programming languages that indices start at 0.
printf("%d\n", numbers[3]);The above statement would print the number 4 as its output. It looks at the array’s 3rd index and finds value 4, which is then used for the print function.
You might ask what if we access an element out of the array’s bounds? While this would throw a runtime error in more modern programming languages, C lets you do this. This is however very dangerous and leads to undefined behavior. It can either produce a garbage value or halt the program via segmentation fault—accessing forbidden memory. This the most common error that C programmers do!
Try it for yourself, pass the array an index of 5 or -1. (-1 refers to the memory location before numbres[0] and 5 refers to the memory location after numbers[4], both produce undefined behavior)
Looping through the array
If you want to print all the elements contained in the array, loop is a relevant mechanism. The only thing you need to check is that the index is not out of bounds!
for (int i = 0; i < 5; i++) {
printf("%d\n", numbers[i]);
}The following code prints the numbers 1 to 5, each on a new line. You need to know the size of the array beforehand, otherwise you do not know where the end is.
That is why it is good idea to define the size before initializing the array. Like this:
const int SIZE = 5;
float array[SIZE] = {4.3, 2, 8.1, 4, 10.2};Sometimes though, we need to get the size of an array on the run. We can do that!
Size of arrays
There is no len or length functions or methods to easily get the actual number of elements in an array. There is however the sizeof() function, which we introduced in a previous lesson. sizeof() tells us how big something is in bytes.
Let’s run the following code:
#include <stdio.h>
int main() {
int nums[] = {1, 2, 5, 7, 99};
printf("Size of nums (int[]): %ld\n", sizeof(nums));
printf("Size of an int: %ld\n", sizeof(int));
printf("Size of the first element of nums: %ld\n", sizeof(nums[0]));
printf("Number of ints in nums: %ld\n", sizeof(nums) / sizeof(int));
printf("Number of elements in nums: %ld\n", sizeof(nums) / sizeof(nums[0]));
return 0;
}$ ./ex
Size of nums (int[]): 20
Size of an int: 4
Size of the first element of nums: 4
Number of ints in nums: 5
Number of elements in nums: 5When we query the array itself, the number of bytes which the array holds is returned. In our case, the returned number is 20. An int value is 4 bytes in size, that means that the number of elements in our array is 5. (20/4 = 5)
For getting the size of one element we can either query the actual data type or if the array is more complex, the first element of the array. Since the size of the first element is int, we can use both approaches in our case.
Strings
Strings in C are very different that the usual string data type in more modern languages. They are very error prone and hard to validate. It is important to know how strings are defined to use them properly.
Definition
C string is simply an array of bytes (characters) terminated with the '\0' nul byte. C’s string functions from the standard library specifically looks for the '\0' so it is needed to end you strings properly!
Strings can be defined in a variety of ways:
// array of characters
char name[] = {'W', 'e', 'c', '\0'};
// array of copied string literal
char name[] = "Wec";
// pointer to a string literal
char *name = "Wec";The first way is to define them as an array of characters. This way you need to specify the ending '\0' nul byte and it doesn’t make much sense if you just want a string.
The prefered way to initialize a string is to use string literal ("Wec") defined by a sequence of characters enclosed in " double quotes. The ending nul byte is automatically included in the string literal.
If you only want a string where its size does not matter, the most idiomatic way is to use char *name = "string";
Right now, you do not need to know what the asterisk * stands for. As of now, look at it as a way to define a string.
Let’s see an example:
#include <stdio.h>
int main() {
char name[4] = {'W', 'e', 'c', '\0'};
printf("Name: ");
for (int i = 0; name[i] != '\0'; i++) {
printf("%c", name[i]);
}
printf("\n");
printf("Name: %s\n", name);
name[1] = '\0';
printf("Name: %s\n", name);
char *hello = "Hello World!";
printf("%s\n", hello);
return 0;
}We first define the name array as a character array. We can either loop through it, until we find nul byte or print it like a string. As you see, both ways work out with the latter being the preferable one of course.
Here is the output:
$ ./ex
Name: Wec
Name: Wec
Name: W
Hello World!We see that changing the second character of name to '\0' messes with the output. Only characters before the first found '\0' are printed. Removing the nul byte completely would lead to undefined behavior, since the string would not be terminated. (Try it!)
At lines 16-17 you can see how you would preferably define and print strings.
Working with program arguments
Now that you know how the arrays and strings work we can look at program’s arguments again. We will go through them and list them this time!
#include <stdio.h>
int main(int argc, char *argv[]) {
for (int i = 0; i < argc; i++) {
printf("%s\n", argv[i]);
}
return 0;
}From what you’ve learned I hope you can see that the notation
char *argv[]
denotes an array of strings.
(e.g. {"hello ", "Wecros", " world", "!"})
So when looking at the code you should see that the output of the program should be all of the entered arguments and the name of the called program (0th argument).
One of the outputs can be:
$ ./args first 234 '"hiya"' last
./args
first
234
"hiya"
last<string.h>
There is a standard library for the purpose of working with strings. There are functions for comparing, copying, searching, concatenation and more! One of the most important functions is:
strlen(const char*)
This function returns the length of the string.
For example:
char *str = "four";
printf("Length of str: %d\n", strlen(str));results in:
Length of str: 4To use this and all the other function you need to include the library in the source file using
#include <string.h>
We might look at the other functions in the future lessons shall we need them.
Conclusion
Congratulations! With this lesson all of the built-in data types are concluded. You’ve made a great progress. You can surely construct some basic programs now! 😊
Next time we are going to go over function constructs in C. Both iterative and recursive.
This is for today, see you in the next lesson! 😁