Complex data types
Structures
A facility for grouping data into composite forms
struct fraction {
int numerator;
int denominator;
};
Usage:
struct fraction f1, f2;
f1.numerator = 22;
f1.denominator = 7;
f2 = f1; // copies over the whole struct
Arrays
A simple type of array in C is one that is declared in place. There are more complication use that are related to pointers.
int scores[100]; //0 to 99 hold 100 integers
Multi dimensional
int board[10][10]; // array of 10x10 integers
Note: It is more efficent to access emmory which is near other reccently accessed memory.
Array of structures
One could easily have an array of structures
struct fraction numbers[1000];
numbers[0].numerator = 22;
Pointers to these data types.
A pointer is a value which represents a reference to another value known as the pointee.
Syntax:
C uses the asterisk * to indicate a pointer, based off of the type pointee.
struct fraction* f1;
// f1 is of type struct fraction*
// *f1 (dereference) is of type struct fraction
// (*f1).numerator is of type int
There is an alternate, more readable syntax for dereferencing a pointer to a structure.
A ->
at the right of the pointer can access any of the fields in the struct.
struct fraction* f1;
f1->numerator; // is of type int
Usage as a node in a linked lsit
```struct node { int data; struct node* next; }
### The & operator
A `&` is on way that pointer is set to point to things. The & operator computes a pointer to the argument to its right. The argument can be any variable which takes up space in the stack or heap (Known as the LValue).
Use & when you ahve some memory an you want a pointer to that memory.
```c
void foo() {
int* p; // p is pointer to an integer
int i; // i is an integer
p = &i; // Set p to point to i
*p = 13; // Change what p points to -- in this case i -- to 13
}
#include <stdio.h>
void foo(int* ptr);
int main(void) {
int* ptr;
int y = 2;
ptr = &y;
foo(ptr);
printf("In main() pointer: %p\n", ptr);
printf("In main() value: %d\n", *ptr);
return 0;
}
void foo(int* ptr) {
int x = 3;
ptr = &x;
printf("In foo() pointer: %p\n", ptr);
printf("In foo() value: %d\n", *ptr);
}
Will output something like :
In foo() pointer: 0x7ffc70ebe864
In foo() value: 3
In main() pointer: 0x7ffc70ebe884
In main() value: 2
This shows that when the local scope is exited the pointer does not retain this value, and that the two pointers here are different.
NULL
A pointer can be assigned a value of 0 to represent that it does not currently have a pointee. A null pointer will behave like a boolean false.
No Promotion
Pointers must match their pointees type.
There is no promotion when creating pointers
#include <stdio.h>
int main(void) {
char x = 5;
int* ptr = &x;
}
Throws:
main.c:6:16: warning: initialization from incompatible pointer type [enabled by default]
int* ptr = &x;
Typedef
A typedef statement introduces a shorthand name for a type.
typedef <type> <name>;
for example
typedef struct treenode* Tree;
struct treenode {
int data;
Tree smaller, larger;
}
Advanced arrays and pointers
In C an array is formed by laying out all of the element contiguously in memeory. The array as a whole is marked by the first element, known as the base address of the whole array.
One can get the address of the nth element with the following process
address of the nth element = address_of_0th_element + (n * element_size_in_bytes)
The [] syntax does this for you.
Related to this is how the + operator works when working on pointers and integers.
[] Gets you the nth element
- Gets you a pointer to the nth element
so for example
(intArray + 3 )
is a pointer to intArray[3]
so
intArray[3]
is equivalent to *(intArray + 3)
Incrementing pointers
If p is a pointer to an element in array then p+1 is thge next element
Alternatively ++p or p++ can be used.
Arrays and pointers
There is no meaningful difference between arrays and pointers. They both look like pointers to C.
It is the programmers responibility to ensure that the elements referred to by a [] or + operation are really there.
One subtle distinction is that an array pointer is constand and can’t be changed. Array parameters are passed as pointers, but they are local?.
Dynamic Arrays
One can create a dynamic array with malloc()
int* b = (int*) malloc(sizeof(int) * 1000);
is equivalent to
int b[1000];
You can even change the size of the array with
b = realloc(b, sizeof(int) * 2000);
Which is equivalent to
int b[2000];