Una lista enlazada consiste en una serie de nodos o elementos donde, además de almacenarse el dato en sí, tiene información que le indica cuál es el nodo siguiente y/o anterior.
En C esto se consigue mediante las estructuras. Una estructura (struct) agrupa un conjunto de variables o campos, y permite trabajar con ella como si se tratara de un tipo de dato más. Y la forma de indicarle a cada nodo cuál es su nodo siguiente es usando variables de tipo puntero en la estructura. 
Un poco de código para que lo entiendas:
  typedef struct _nodo {
    int valor;
    _nodo* anterior;
    _nodo* siguiente;
 } nodo;
 Las variables anterior y siguiente son punteros a nodo, es decir, enlazan el nodo actual a otros nodos. Así para enlazar dos nodos, únicamente debes poner algo como:
 
  nodo1.siguiente = &nodo2;
  nodo1.anterior  =  &nodo0;
En una lista enlazada lo normal es que haya un nodo que sea el primero y otro que sea el último. Estos casos son especiales. El primer nodo, su puntero anterior apuntará a NULL, es decir, no existe un nodo anterior. El último nodo es similar, pero con el puntero a siguiente.
Por último, para recorrer una lista enlazada, basta con crear una variable auxiliar que sea puntero a nodo:
  
  nodo* aux;
Luego, con un bucle se puede recorrer toda la lista de la siguiente manera (es solo un ejemplo):
 aux = &primer_nodo;
 while (aux != NULL) {
    aux = aux->siguiente;
    // ... y lo que sea
 }
Básicamente, la idea es jugar con esto. No he querido entrar en más detalle porque creo que esto te será suficiente. No obstante, si necesitas ayuda sobre punteros, o sintaxis de C, no dudes en preguntar.