C program to print a triangle of stars
I use a string to avoid the inner loop. The problem here is the printf() inside. A 3000-row triangle redirected to /dev/null takes 50ms, but now only 4ms.
I reformatted the output. And I left dots as fillers to see what is going on.
$ ./a.out 
...*...
..***..
.*****.
*******

It starts with one * in the so-called middle, and every row-iteration only sets two more bytes to * before it prints.
The complicated part is preparing the string i.e. array of chars. You can use calloc() to clear the right side, but it still takes a step to put blanks on the left side.
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

int trihi = 4;
char PIX = '*';

int main(void){

    int width = trihi * 2 - 1;
    char s[width + 1];
    memset(s, '.', width);
    s[width] = '\0';

    int mid = trihi - 1;
    s[mid] = PIX;
    printf(&quot;%s\n&quot;, s);

    for (int i = 1; i &lt; trihi; i++) {

        s[mid - i] =
        s[mid + i] = PIX;
        printf(&quot;%s\n&quot;, s);
    }
}

This should add up. s[mid + i] runs up to 2*mid = 2*(trihi-1).
The '\0' sits at width = 2*trihi - 1 which is one higher, and is the highest legal index for s.
It is very easy to make a small mistake and not have the \0 at the correct place.
It also works with a triangle height of 1:
$ ./a.out 
*

And by setting ... = --PIX; in the loop:
$ ./a.out 
.....*.....
....)*)....
...()*)(...
..'()*)('..
.&amp;'()*)('&amp;.
%&amp;'()*)('&amp;%

The So-Called Middle
This is how a triangle of height 4 is laid out. Size is 8. The middle is s[3]; there are 3 spaces to the left.
01234567  --- &quot;offset&quot;, &quot;index&quot;
...*...0
|  |   |
|  |   +-- s[width]  (width = 2*trihi - 1)     
|  +------ s[mid]    (mid   = trihi - 1)   
+--------- s[0] 

You start with trihi=4, but what you need is mostly 3 and 7...the geometrical base width is also 7.

Just any Triangle
If this is enough (with original height = 3):
$ ./a.out 
*
**
***

then the code gets much simpler:
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

int trihi = 3;
char PIX = '*';

int main(void){

    char *s = calloc(trihi+1, 1);

    for (int i = 0; i &lt; trihi; i++) {
        s[i] = PIX;
        printf(&quot;%s\n&quot;, s);
    }
}

I kicked everything out except the basic idea: re-using a prepared string/array. Here the calloc-zeroes are only after the PIXes. No need for a filler like space or dots via memset() anymore. But it is also not the same user experience...and the triangle is half the size.
Overiq.com has a double-loop version of a C Program to print Half Pyramid pattern using *. It takes much longer than the above (tri2.c below).
$ gcc -O2 over.c           
$ time ./a.out |wc -l
3001

real    0m0.029s
user    0m0.020s
sys     0m0.014s
$ gcc -O2 tri2.c 
$ time ./a.out |wc -l
3000

real    0m0.006s
user    0m0.000s
sys     0m0.011s