CIT 593 Intro to Computer Systems Lecture #17 (11/13/12) Arrays An array is a collection of values. In C, as in many other languages: all elements of the array must be of the same type the number of elements in the array is fixed For instance, we can declare an array of five ints like this: int numbers[5]; Each element of the array can be accessed by a 0-based index (meaning, the first element has index 0). numbers[4] = 2; int x = numbers[2] + 4; Note that, unlike in Java, there is nothing in C to stop you from going outside the bounds of the array. For instance, with the five-element array declared above, both of the following are perfectly legal (though perhaps not desirable): numbers[8] = 11; numbers[-2] = 3; What is the implication of doing something like that? Let s look at this example: int even[] = { 2, 4, 6, 8, 10 }; int odd[] = { 1, 3, 5, 7, 9 }; Note the shorthand notation for declaring and initializing the elements of an array. If these were local variables, i.e. declared on the stack, they would look like this: 1 odd[0] 3 odd[1] 4 odd[2] 5 odd[3] 9 odd[4] 2 even[0] 4 even[1] 6 even[2] 8 even[3] 10 even[4] That is, the five elements of even would be put on the stack first, and on top of those would be the five elements of odd. The symbol table keeps track of the starting address (relative to the FP) of the starts of each array. So when you access odd[2], it finds the start of the odd array and then goes down two addresses to get the right spot in memory.
So, what happens when you do this? odd[6] = -1; As you can imagine, it will go down six addresses from the start of the odd array, and it will change that value, giving us this: 1 odd[0] 3 odd[1] 4 odd[2] 5 odd[3] 9 odd[4] 2 even[0] -1 even[1] 6 even[2] 8 even[3] 10 even[4] So in this case, we have overwritten the value of even[1]. Arrays and Functions There are two important rules to remember when it comes to using arrays with functions. 1. Unlike in Java, in which arrays are objects, in C there is no standard way to know the number of elements in an array. 2. Unlike primitive datatypes, which are passed by value, arrays are passed by reference. This means that, if you pass an array to a function that changes that array, the array itself is actually changed To address issue #1, it is typical in C to pass not only the array itself to a function, but also an int representing the number of elements in the array. The implication of issue #2 is that you do need to be careful about side effects. For example, here s a function that will multiply every element in the array by -1. void negate(int array[], int length) { int i = 0; for (i = 0; i < length; i++) { array[i] *= -1; } } So if you called that function like this: int numbers[] = { 1, 4, 5, 9 }; negate(numbers, 4);
Then, when the function returns, numbers[0] would be -1, numbers[1] would be -4, and so on. Two-Dimensional Arrays As in most other programming languages, you can have arrays of arrays, or what is more commonly known as two-dimensional arrays. int numbers[4][6]; numbers[2][3] = 19; Strings In C, a string is simply an array of chars. As we saw in LC-3, strings are null-terminated, meaning that the last element of the array is null, which is ASCII value 0. For instance, we can declare a string like this: char name[] = Joe ; On the stack, it would look like this: J name[0] o name[1] e name[2] 0 name[3] Note that name is a four-element char array (because of the terminating null), not three. We can print strings using the %s placeholder with printf: printf( Hello, %s.\n, name); would print Hello, Joe. Just like other arrays, we can change the individual elements: name[1] = a ; printf( Hello, %s.\n, name); would now print Hello, Jae. We can also read strings using %s with scanf: scanf( %s, &input); Keep in mind that scanf will put the terminating null at the end of whatever is entered, but it will not attempt to squeeze everything into the space allocated for the input.
For instance, if the user typed abc123, then on the stack we d have: a input[0] b input[1] c input[2] 1 input[3] 2 input[4] 3 input[5] 0 input[6]? input[7]? input[8]? input[9] In this case, input[6] would get the null value, but the last three chars would not be modified and thus would likely be unknown. But what if the user entered helloworld, which is 10 characters? Then the stack would be like this: h input[0] e input[1] l input[2] l input[3] o input[4] w input[5] o input[6] r input[7] l input[8] d input[9] 0 Other variable Note that, in this case, the null value overwrites whatever variable happened to be below input on the stack. This can lead to all sorts of trouble, as you ll see in other courses. To address this, you can specify the number of characters to read from scanf like this: scanf( %9s, &input); In this case, the %9s means only read the first nine characters. Keep in mind that you shouldn't use %10s in this case, because you need one extra space for the null in the array input.
You can determine the length of a string by using the strlen function. It counts the characters in the string up until the null, and returns the count (note that the return value does not include the null). scanf( %s, &input); if (strlen(input) > 9) PROBLEM!