when you start with the static value like "if ( 0 < text.strings) it is not very readable. if(text.strings > 0) is much more clear, because we tend to read code from left to right.
Code
if (text_lines->strings > 0 && text_lines->strings >  line_number )


Concerning an invalid pointer in your original example: If you do (text.>pstring)[line_number] you can get out of bounds. It is always better to store the string number somewhere or rely on text.strings like you said and check that in your if too. Because if your array is out of bounds it is not NULL it accesses the next memoryblock and compares NULL == [messy messy pointer after array memory block]