Did programmers just check the format specifications in the format string and/or test with max values to determine how many characters sprintf would output to the string?
You have to understand the original reasoning behind C's I/O library. It was initially a "quick and dirty" approach to providing some utility and file I/O. Recall that early Algol had no defined I/O statements! Originally, the thinking was that I/O is implementation-dependent and could be accommodated through user-provided procedure calls. The same goes for string (well, array of characters) handling (e.g. strcat). So you use the length-specified stuff when available and appropriate; otherwise, you exercise caution when using unspecified length stuff.
There are lots of ways C programs can fall into a pit. Consider, for example, the simple statement:
Code:
static char *x = "Hello";
strcpy(x+1, x);
Recall that C was originally an alternative to assembly.