Armstrong numbers in C
This is a well-written program.  It is clear and easy to follow, which are attributes of good software.  With that said, there are still some things that you can do to speed up the performance of the code and there are a few minor comments on formatting.  I'm hoping they will help you improve your code.

Avoid peculiar formatting

I have been programming in C for many, many years, but this line threw me for a moment:

while (b --&gt; 1) { a *= original_a;}


It was the --&gt; that was odd, but of course, it is actually equivalent to this:

while (b-- &gt; 1) { 
    a *= original_a;
}


Formatting for clarity, including keeping operators attached to their variables and avoiding one-liners helps others read and understand your code.

Avoid expensive mathematical operations where practical

To speed things along, we can replace this code

int digits_len(int n) {
    int length = 0;
    while(n) {
        n /= 10;
        length++;
    }
    return length;
}


With this:

int digits_len(int n) {
    if (n &lt; 10) return 1;
    else if (n &lt; 100) return 2;
    else if (n &lt; 1000) return 3;
    else if (n &lt; 10000) return 4;
    else if (n &lt; 100000) return 5;
    else if (n &lt; 1000000) return 6;
    else if (n &lt; 10000000) return 7;
    else if (n &lt; 100000000) return 8;
    return 9;
}


It's longer but it avoids the computationally costly division and avoid a loop.  Note, however, that it does not produce sensible results for negative numbers.  It seemed likely that this was acceptable for the increase in speed gained for this program.

Use a table lookup instead of a loop

The power routine, in context, has the property that neither a nor b are greater than 9. With that observation, it's possible to replace the routine with a simple table lookup.  Here's what I used:

const int powtable[10][10] = {
    { 0, 0, 0*0, 0*0*0, 0*0*0*0, 0*0*0*0*0, 0*0*0*0*0*0, 0*0*0*0*0*0*0, 0*0*0*0*0*0*0*0, 0*0*0*0*0*0*0*0*0 },
    { 0, 1, 1*1, 1*1*1, 1*1*1*1, 1*1*1*1*1, 1*1*1*1*1*1, 1*1*1*1*1*1*1, 1*1*1*1*1*1*1*1, 1*1*1*1*1*1*1*1*1 },
    { 0, 2, 2*2, 2*2*2, 2*2*2*2, 2*2*2*2*2, 2*2*2*2*2*2, 2*2*2*2*2*2*2, 2*2*2*2*2*2*2*2, 2*2*2*2*2*2*2*2*2 },
    { 0, 3, 3*3, 3*3*3, 3*3*3*3, 3*3*3*3*3, 3*3*3*3*3*3, 3*3*3*3*3*3*3, 3*3*3*3*3*3*3*3, 3*3*3*3*3*3*3*3*3 },
    { 0, 4, 4*4, 4*4*4, 4*4*4*4, 4*4*4*4*4, 4*4*4*4*4*4, 4*4*4*4*4*4*4, 4*4*4*4*4*4*4*4, 4*4*4*4*4*4*4*4*4 },
    { 0, 5, 5*5, 5*5*5, 5*5*5*5, 5*5*5*5*5, 5*5*5*5*5*5, 5*5*5*5*5*5*5, 5*5*5*5*5*5*5*5, 5*5*5*5*5*5*5*5*5 },
    { 0, 6, 6*6, 6*6*6, 6*6*6*6, 6*6*6*6*6, 6*6*6*6*6*6, 6*6*6*6*6*6*6, 6*6*6*6*6*6*6*6, 6*6*6*6*6*6*6*6*6 },
    { 0, 7, 7*7, 7*7*7, 7*7*7*7, 7*7*7*7*7, 7*7*7*7*7*7, 7*7*7*7*7*7*7, 7*7*7*7*7*7*7*7, 7*7*7*7*7*7*7*7*7 },
    { 0, 8, 8*8, 8*8*8, 8*8*8*8, 8*8*8*8*8, 8*8*8*8*8*8, 8*8*8*8*8*8*8, 8*8*8*8*8*8*8*8, 8*8*8*8*8*8*8*8*8 },
    { 0, 9, 9*9, 9*9*9, 9*9*9*9, 9*9*9*9*9, 9*9*9*9*9*9, 9*9*9*9*9*9*9, 9*9*9*9*9*9*9*9, 9*9*9*9*9*9*9*9*9 }
};
inline int power(int a, int b) {
    return powtable[a][b];
}


The multiplications in the table are all done at compile-time rather than at runtime, so they cost essentially nothing.  (I could, of course, have simply placed the appropriate numbers into the table, but I'm very lazy and prefer to make the computer do all the work!)

Avoid unused arguments

The main routine has the usual arguments of argc and argv but argc is never used.  If you compile with all warnings turned on (which I would recommend), the compiler will correctly complain about the unused variable.  I decided to use it and also to give a hint to the user as to how to use the program:

if (argc &lt; 2) {
    puts("Usage: armstrong maxint\n");
    return 0;
}


Keep using assert

It's refreshing to see code from an avowed beginner at C using assert rationally and correctly.  Bonus points for you!  Also, although I didn't, you might wish to use asserts to assure that the parameters passed to power are indeed both less than 10.

Results

On my machine, the original code, when compiled with -O2 using gcc version 4.9.2 on a 64-bit Linux box, the code runs in 8.1 seconds.  With the changes mentioned above, it runs in 2.4 seconds, or almost 4x faster.