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];
Written on September 15, 2017