ant2009
ant2009

Reputation: 22486

sub-specifiers in printf statement for width and precision

gcc (GCC) 4.1.2
c89

The code:

LOG(DEBUG, "state changed [ %d ] [ %.*s ]",
    call_id,
    (int)call_info.state_text.slen,
    call_info.state_text.ptr);

I am just wondering about the %.*s according to the man pages.

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

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

1) I am just wondering what is the difference between the width and the precision in the above printf statement.

2) The second argument is an integer that will be the length of the string to print out. However, all strings should be nul terminated so how would you get the length of the string in the first place?

3) Is there any reason you can't do the following instead?

LOG(DEBUG, "state changed [ %d ] [ %s ]",
    call_id,
    call_info.state_text.ptr);

4) What is the real purpose of using the * and .* sub-specifiers?

Upvotes: 1

Views: 2771

Answers (3)

Yu Hao
Yu Hao

Reputation: 122383

For %s format specifier in printf family functions:

width like %5s is for minimum field width.

precision like %.5s is for maximum number of bytes to be written.

The * specifier which indicates that an additional int argument will be supplied as the field width or precision. Despite that, it has no effect on the difference between width and precision format.

Related C standard:

C11 §7.21.6.1 The fprintf function

An optional minimum field width. If the converted value has fewer characters than the field width, it is padded with spaces (by default) on the left (or right, if the left adjustment flag, described later, has been given) to the field width. The field width takes the form of an asterisk * (described later) or a non negative decimal integer.

An optional precision that gives the minimum number of digits to appear for the d, i, o, u, x, and X conversions, the number of digits to appear after the decimal-point character for a, A, e, E, f, and F conversions, the maximum number of significant digits for the g and G conversions, or the maximum number of bytes to be written for s conversions. The precision takes the form of a period (.) followed either by an asterisk * (described later) or by an optional decimal integer; only if the period is specified, the precision is taken as zero. If a precision appears with any other conversion specifier, the behaviour is undefined.

Upvotes: 2

egur
egur

Reputation: 7960

These are mostly used in printing numbers (int, float) but they are also useful for strings.

* is used to set the minimum length of the output string.

.* is used to set the maximum length of the input string.

*.* is used to set the maximum length of the input string and the minimum length of the output string.

Examples:

printf("%*s\n", 3, "ABCDE");
printf("%.*s\n", 3, "ABCDE");
printf("%*.*s\n", 5, 3, "ABCDE");

Output:

ABCDE
ABC
  ABC

Upvotes: 3

user3007735
user3007735

Reputation: 159

* -> The width is not specified in the format string, but as an additional integer value argument preceding the argument thus has to be formatted.

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

You can read more here. Link

Upvotes: 1

Related Questions