I have this:

typedef struct {
    int value;
} Thing;

void doSomething(Thing *ptr) {
    ptr = (Thing *)calloc(5, sizeof(Thing));
    int i;
    for(i = 0; i < 5; i++) {
        scanf("%d", (ptr[i]).value);
    }
}

int main() {
    Thing t;
    doSomething(&t);
}

Which crashes at the scanf() line. How should I be writing it instead?

line 9: that should be scanf("%d", &(ptr[i]).value);

There are a couple of problems here. One is that the pointer you passed to doSomething() is a reference to a concrete object. When you allocate the array to that, you have corrupted memory - BOOM! SEGFAULT...

You need to pass a pointer to a pointer, and then you can allocate your array. IE,

#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int value;
} Thing;

void doSomething(Thing **ptr)
{
    int i;
    *ptr = (Thing *)calloc(5, sizeof(Thing));
    for(i = 0; i < 5; i++)
    {
        (*ptr)[i].value = i;
    }
}
int main()
{
    Thing* t = 0;
    int i;
    doSomething(&t);

    for (i = 0; i < 5; i++)
    {
        printf("Thing[%d].value == %d\n", i, t[i].value);
    }
    return 0;
}

A couple of points in addition.

  1. Make sure main() returns an integer value.
  2. Initialize variables (especially pointer types) before you use them.