Substrings With Printf

You can specify a precision with printf’s %s conversion to limit how many characters are printed:

const char *greeting = "Hello, World!\n";
printf("%.5s\n", greeting);  // prints "Hello\n"

But what if you don’t know until runtime how many characters you need?

From man 3 printf:

Instead of a decimal digit string one may write “*” or “*m$” (for some decimal integer m) to specify that the precision is given in the next argument, or in the m-th argument, respectively, which must be of type int.

This is awesome for printing substrings. Example:

struct token {
    const char *start;    // start of the token inside a source string
    int length;           // number of characters in the token
};

void print_token(FILE *out, struct token token)
{
    fprintf(out, "<\"%.*s\">", token.length, token.start);
}

The “*m$” syntax comes from a POSIX extension to the C standard that lets you specify which argument to use for each conversion. This is helpful if you want to use the same argument more than once:

void print_token(FILE *out, struct token token)
{
    fprintf(out, "<\"%1$.*2$s\" (%2$d characters)>",
            token.start, token.length);
}

Note that you can’t mix numbered and unnumbered conversions in the same format string, so if you use *m$ for the precision, you also need to use %m$ for the conversion itself.