163

I got a code snippet in which there is a

printf("%.*s\n")

what does the %.*s mean?

hippietrail
  • 15,848
  • 18
  • 99
  • 158
StevenWang
  • 3,625
  • 4
  • 30
  • 40

4 Answers4

161

You can use an asterisk (*) to pass the width specifier/precision to printf(), rather than hard coding it into the format string, i.e.

void f(const char *str, int str_len)
{
  printf("%.*s\n", str_len, str);
}
BaCaRoZzo
  • 7,502
  • 6
  • 51
  • 82
AusCBloke
  • 18,014
  • 6
  • 40
  • 44
  • 9
    It should be noted that the `str_len` argument must have type `int` (or narrower integral type, which would be promoted to `int`). It would be a bug to pass `long`, `size_t`, etc. – M.M Jul 07 '15 at 22:03
  • 16
    It's worth mentioning that the likely purpose of this code, especially when used with `%s`, is to print a sub-string of the original string. In this use case, `str` would point to somewhere inside the original string (possibly at the beginning), and `str_len` will specify the length of the sub-string that should be printed. – Sonic Atom Jan 25 '16 at 13:37
  • 4
    By specifying a length, we can get around printing (or sprintf) 'ing a string which has no null terminator, for example a string which is input from any stream or file based source. Which is far more often the use case I have encountered, than merely print prettines. –  Oct 24 '18 at 08:04
48

More detailed here.

integer value or * that specifies minimum field width. The result is padded with space characters (by default), if required, on the left when right-justified, or on the right if left-justified. In the case when * is used, the width is specified by an additional argument of type int. If the value of the argument is negative, it results with the - flag specified and positive field width. (Note: This is the minimum width: The value is never truncated.)

. followed by integer number or *, or neither that specifies precision of the conversion. In the case when * is used, the precision is specified by an additional argument of type int. If the value of this argument is negative, it is ignored. If neither a number nor * is used, the precision is taken as zero. See the table below for exact effects of precision.

So if we try both conversion specification

#include <stdio.h>

int main() {
    int precision = 8;
    int biggerPrecision = 16;
    const char *greetings = "Hello world";

    printf("|%.8s|\n", greetings);
    printf("|%.*s|\n", precision , greetings);
    printf("|%16s|\n", greetings);
    printf("|%*s|\n", biggerPrecision , greetings);

    return 0;
}

we get the output:

|Hello wo|
|Hello wo|
|     Hello world|
|     Hello world|
Ondrej
  • 817
  • 1
  • 9
  • 16
  • 1
    From the docs, the major difference between '%.*s' and '%*s' seems to be that the former ignore negative values for precision while the later takes in into consideration to apply the appropriate justification. – powersource97 Sep 17 '21 at 03:03
  • 2
    You could also add `printf("|%.*s|\n", biggerPrecision , greetings);` – kenn Dec 27 '21 at 20:50
13

I don't think the code above is correct but (according to this description of printf()) the .* means

The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.'

So it's a string with a passable width as an argument.

Dan D.
  • 73,243
  • 15
  • 104
  • 123
rerun
  • 25,014
  • 6
  • 48
  • 78
  • 2
    I've added the URL cross-reference so you can avoid charges of plagiarism. Of course, the correct quote says "The _precision_ is not …" rather than "The _width_ is not…". – Jonathan Leffler Mar 30 '15 at 04:52
  • 1
    As @MattMcNabb pointed out, every reference to that page must highlight that “*an integer value*” is exactly `int` (or a subset of it) — not just any integral value like more intuitive `size_t` or its possible aliases, like `std::string::size_type`. This is even more confusing, taking into account that the referenced page mentions `size_t` as one of supported type specifiers. – Anton Samsonov Aug 04 '15 at 18:04
11

See: http://www.cplusplus.com/reference/clibrary/cstdio/printf/

.* The precision is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted.

s String of characters

Community
  • 1
  • 1
Josh
  • 12,448
  • 10
  • 74
  • 118