1) 
Для каких типов данных я должен выделить память с помощью malloc?
- Для таких типов, как structs, указатели, кроме базовых типов данных, например int
- Для всех типов?
  2) 
Почему я могу запустить этот код? Почему он не падает? Я предположил, что мне нужно сначала выделить память для структуры.
#include <stdio.h>
#include <stdlib.h>
typedef unsigned int uint32;
typedef struct 
{
  int a;
  uint32* b;
}
foo;
int main(int argc, char* argv[])
{
 foo foo2;
 foo2.a = 3;
 foo2.b = (uint32*)malloc(sizeof(uint32));
 *foo2.b = 123;
}
Не лучше ли использовать
foo* foo2 = malloc(sizeof(foo));
3) Как установить foo.b? Имеется ли эталонная случайная память или NULL?
#include <stdio.h>
#include <stdlib.h>
typedef unsigned int uint32;
typedef struct 
{
  int a;
  uint32* b;
}
foo;
int main(int argc, char* argv[])
{
 foo foo2;
 foo2.a = 3;
}
