How to use scanf width specifier at 0?

How to use scanf width specifier for 0?
1) unlimited width (see cywin gcc 4.5.3 Version)
2) UB
3) something else?

My application (not shown) dynamically generates a width specifier as part of a larger format string for scanf (). Rarely would this create "%0s" in the middle of a format string. In this context, the destination string for this %0s has only 1 byte of room for scanf() to store \0 , which with behavior # 1 above causes problems.

Note. The following test cases use persistent formats.

 #include <memory.h> #include <stdio.h> void scanf_test(const char *Src, const char *Format) { char Dest[10]; int NumFields; memset(Dest, '\0', sizeof(Dest)-1); NumFields = sscanf(Src, Format, Dest); printf("scanf:%d Src:'%s' Format:'%s' Dest:'%s'\n", NumFields, Src, Format, Dest); } int main(int argc, char *argv[]) { scanf_test("1234" , "%s"); scanf_test("1234" , "%2s"); scanf_test("1234" , "%1s"); scanf_test("1234" , "%0s"); return 0; } 

Output:

 scanf:1 Src:'1234' Format:'%s' Dest:'1234' scanf:1 Src:'1234' Format:'%2s' Dest:'12' scanf:1 Src:'1234' Format:'%1s' Dest:'1' scanf:1 Src:'1234' Format:'%0s' Dest:'1234' 

My question is about the last line. Width 0 seems to lead to a width limit, not a width of 0. If this is the correct behavior or UB, will I have to approach the situation with zero width in a different way or are there other scanf () formats to consider?

+7
source share
2 answers

The maximum field width specifier must be nonzero. C99, 7.19.6.2:

The format must be a multi-byte sequence of characters, starting and ending with the initial state of the shift. The format consists of zero or more directives: one or more white spaces of characters, an ordinary multibyte character (neither % , nor a space character), or a specification change. Each conversion specification is entered with a % character. After % , the following lines are displayed in sequence:
- Optional symbol of assignment suppression * .
- An optional non-zero decimal integer that defines the maximum field width (in characters).
- An optional length modifier that determines the size of the receiving object.
- Transform specifier symbol that indicates the type of transform to apply.

So, if you use 0 , the behavior is undefined.

+10
source

This came from 7.21.6.2 of n1570.pdf (standard draft C11):

After%, the following sequences appear:

- Additional character of suppression of assignment *.

- an optional decimal integer greater than zero that defines the maximum field width (in characters).

...

This behavior is undefined because the C standard states that the maximum field width must be greater than zero.

An input element is defined as the longest sequence of input characters that does not exceed a given field width and ...

What do you want to achieve by reading a field of width 0 and assigning it as a string (empty string) to Dest ? What actual problem are you trying to solve? It seems more straightforward to simply assign as *Dest = '\0'; .

+4
source

All Articles