Printing a heartbeat (heart star) animation
Welcome to CodeReview! The program doesn't look too bad, however there are some ways to improve it:
Naming things
The biggest issue with your code is that there is a bunch of single-letter variable names (i...k), some magic constants (2, 3, 4, 17 and 99), and nested while-loops. If I wasn't told what this program would do and didn't run it for myself, I would have no clue reading this code what it is going to do. However, if you would give (better) names to things, it might explain what everything means to the reader. That includes you yourself in the future!
Let's start with the outer loop:
int main() {
    for (int i = 0; i &lt; 99; i++) {
         int size = i % 3;
         clear_screen();
         draw_heart(size);
         usleep(200000);
    }
}

Keeping i as a generic loop counter is OK, as this is so commonplace that a longer name is not going to make this more readable. But I renamed h to size. Then I assume you have created two functions, one for clearing the screen, and another for drawing a heart of a given size. If you now read this code, you can very quickly see that you are repeatedly drawing a heart of a varying size, without requiring any comments.
Here is the function to clear the screen:
void clear_screen(void) {
    // Use ANSI escape codes to clear the screen
    printf(&quot;\e[1;1H\e[2J&quot;);
    printf(&quot;\e[?25l&quot;);
}

The name of the function alone is already enough to know what the function tries to do, the comment here is to explain the weird characters that are printed. Someone who doesn't recognize these escape codes now knows what these are, and can search for &quot;ANSI escape codes&quot; to find out more about them.
The constants you have in your code could be given names, like so:
void draw_heart(int size) {
    static const int top_size = 3;
    static const int bottom_size = 9;
    ...
}

And then used consistently in the calculations you use, such that if you want to change the size of the heart, you can just change these constants.
Use for-loops where appropriate
You are using a lot of while-loops in cases where you can more clearly write for-loops. Any time you initialize a variable, run while the variable satisfies some condition, and then update that variable, use for, like so:
void draw_heart(int size) {
    // Draw two small upward pointing triangles
    for (int i = 0; i &lt; 3; i++) {
        for (int j = 0; i &lt; (2 - i) * 2 + size; j++) {
           printf(&quot; &quot;);
        }

        ...
    }

    // Draw one large downward pointing triangle
    for (int i = 0; i &lt; 9; i++) {
        ...
    }
}

The advantage is that in one line you combine all this information, so just from reading that line you can see what the start condition is, what the end condition is and how the variable is updated every step.