<!-- language-all: lang-c -->

#C, <s>91</s> <s>89</s> <s>80</s> 74 bytes

    w,y;f(s){for(y=-s;++y<s;)for(w=printf("\n%*s",y,"");++w<s*printf(" *"););}

I pretty much tweaked around to get the correct formulas, then mashed it all together.

Call `f` with the number *n*, and it will print the hexagon to stdout.

**Ungolfed and explained (80-byte version):**

    w,y;
    f(s) {
        // y iterates over [-s + 1 ; s - 1] (the number of rows)
        for(y = -s; ++y < s;)
            // w iterates over [abs(y) + 2 ; s * 2 - 1] (the number of stars on the row)
            for(
                // This prints a backspace character (ASCII 8)
                // padded with abs(y) + 2 spaces, effectively
                // printing abs(y) spaces to offset the row.
                // Also initializes w with abs(y) + 2.
                printf("\n%*c", w = abs(y) + 2, 8);

                // This is the for's condition. Makes use
                // of the 2 returned by printf, since we coïncidentally
                // need to double the upper bound for w.
                w++ < s * printf("* ");

                // Empty for increment
            )
                ; // Empty for body
    }

[See it live on Coliru](http://coliru.stacked-crooked.com/a/f65c2157dcac791b)

**Notes:**

- `printf` can handle negative padding, which results in a left-aligned character with the padding on the right. Thus I tried something to the effect of `w = printf("%*c*", y, ' ')` so it would take care of the absolute value, and I could retrieve it from its return value. Unfortunately, both zero and one padding widths print the character on its own, so the three center lines were identical.  
**Update:** [Jasen](https://codegolf.stackexchange.com/users/34589/jasen) has found a way to do exactly this by printing an empty string instead of a character -- 6 bytes shaved off!

- The backspace character is handled incorrectly by Coliru -- executing this code on a local terminal does remove the leading space on each line.