Arrays & Debugging in C
Arrays
An array consists of contiguous memory locations:
- The highest address corresponds to the last element.
- The lowest address corresponds to the first element.
Declaring Arrays
Arrays can be declared like so:
float income[3];
This will create an array called income
of type float
that can hold three elements.
Initialising Array
Arrays can be assigned in the following ways:
income[0] = 198.76;
income[1]= 236.89;
income[2] = 218.54;
float income[3] = {198.76, 236.89, 218.54};
This syntax is only available when declaring new arrays.
Arrays can be partially initialised:
float income[3] = {198.76, 236.89};
The rest of the values are zero.
float income[];
The array contains garbage.
Multi-dimensional Arrays
We can declare and assign multi-dimensional arrays like so:
int arr[2][3]; /* not arr[2, 3] */
int i, j;
int sum = 0;
arr[0][0] = 12;
arr[0][1] = 23;
arr[0][2] = 34;
arr[1][0] = 45;
arr[1][1] = 56;
arr[1][2] = 67;
for ( i=0; i<2; i++ ) {
for ( j=0; j<3; j++ ) {
sum += arr[i][j];
}
}
printf("sum = %d\n", sum);
This structure is laid out in memory with the all elements of arr[0] first, then arr[1] and so on.
When assigning implicitly, all but the leftmost dimension must be specified:
int my_array[][3] = {{12, 23, 34}, {45, 56, 67}};
Passing Arrays to Functions
As arrays are a pointer to their first element we can pass them to functions without passing a pointer:
void foo(int arr[]) {
arr[0] = 12;
}
int arr[] = {1, 2, 3}
foo(arr);
If we did this with a single value then the change wouldn’t be reflected outside the scope of the function.
Debugging
Both lldb
and gdb
are nice tools for debugging C but I will be using `gdb.
Before running code in a debugger it is nice to rememeber to include debugging symbols with -g:
gcc -Wall -g test.c -o test
Open the file with the debugger with:
gdb test
Breakpoints
By setting a breakpoint we are able to step through the code:
b main
We can also use linenumbers for this.
TUI Layouts
To see our code we can run:
layout src
If we have already set a layout before we can run tui enable
to get to our last layout.
Stepping Through Code
We can step through our code with the following commands:
Command | Description |
---|---|
n , next |
Steps to the next line. |
s , step |
Steps into the current line’s function. |
c , continue |
Continue until the next breakpoint. |
finish |
Finishes execution of the current function and then pauses. |
Variables
We can use the following commands to inspect variables:
Command | Description |
---|---|
p <var> , print <var> |
Prints the varaibles current value. |
watch <var> |
Prints the variable whenever it changes. |
i lo , info locals |
Prints all arguments and local variables. |
We can also modify variables:
set var i = 2
Frames
If you have several nested functions then you can use the following commands to navigate up and down the calling stack to view what is running at each level:
Command | Description |
---|---|
f , frame |
Shows the current line/frame you are in. |
up |
Moves up the calling stack one level. |
down |
Moves down the calling stack one level. |
ba , backtrace |
Shows the full calling stack. |