until very recently I was sure I understood the handling of the "%n"
format spec of scanf() and its variants:
- no input action
- but a conversion
- with an assignment that can be suppressed
- that does never contribute to the return value of scanf()
And then I stumbled about the following notice in a scanf() manpage (glibc):
'[...]The C standard says: "Execution of a %n directive does not
increment the assignment count returned at the completion of execution"
but the Corrigendum seems to contradict this. Probably it is wise not
to make any assumptions on the effect of %n conversions on the return
value.'
I googled around (including the comp.std.c archive) for some time, but I
found no further references that would substantiate that warning.
Could some std gurus enlighten me: Is there a grain of truth, or is this
warning based on a wrong interpretation?
thanks for any answers
True.
> - but a conversion
False. It performs no conversion (although it consumes an argument)
> - with an assignment that can be suppressed
False. If you try to suppress assignment or if you specify a field
width, the behaviour is undefined
> - that does never contribute to the return value of scanf()
That is probably intended, but can not be readily deduced from a
literal reading of the standard.
>
> And then I stumbled about the following notice in a scanf() manpage (glibc):
>
> '[...]The C standard says: "Execution of a %n directive does not
> increment the assignment count returned at the completion of execution"
> but the Corrigendum seems to contradict this. Probably it is wise not
> to make any assumptions on the effect of %n conversions on the return
> value.'
>
> I googled around (including the comp.std.c archive) for some time, but I
> found no further references that would substantiate that warning.
>
> Could some std gurus enlighten me: Is there a grain of truth, or is this
> warning based on a wrong interpretation?
I am not sure what Corrigendum your quote refers to. In my copy of the
standard (C99 + TC1), it is still stated that the %n directive does
not contribute to the assignment count of fscanf. The text explicitly
refers to the fscanf function here.
Taken literally, this could mean the %n directive has slightly
different semantics for fscanf and the other *scanf incarnations, but
I doubt that was the intention.
>
> thanks for any answers
Bart v Ingen Schenau
You should probably grab a newer draft;
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
includes C99 + TC1 + TC2 + TC3. All changes from C99 are marked with
change bars.
Here's the relevent part of the scanf(3) man page on my system, probably
the same one juergen has:
n Nothing is expected; instead, the number of characters
consumed thus far from the input is stored through the
next pointer, which must be a pointer to int. This is not
a conversion, although it can be suppressed with the *
assignment-suppression character. The C standard says:
"Execution of a %n directive does not increment the
assignment count returned at the completion of execution"
but the Corrigendum seems to contradict this. Probably it
is wise not to make any assumptions on the effect of %n
conversions on the return value.
Here's the description from N1256 7.19.6.2p12 (there are no change
bars, so none of the three Corrigenda appear to have addressed this):
n No input is consumed. The corresponding argument shall be
a pointer to signed integer into which is to be written
the number of characters read from the input stream so
far by this call to the fscanf function. Execution of a %n
directive does not increment the assignment count returned
at the completion of execution of the fscanf function. No
argument is converted, but one is consumed. If the conversion
specification includes an assignment-suppressing character
or a field width, the behavior is undefined.
scanf "is equivalent to fscanf with the argument stdin interposed before
the arguments to scanf" (7.19.6.4p1), and sscanf "is equivalent to
fscanf, except that input is obtained from a string (specified by the
argument s) rather than from a stream" (7.19.6.7p2; there's a bit more
there, but nothing that affects %n). So there's no issue of different
semantics for fscanf vs. scanf vs. sscanf.
The man page's statement that "it can be suppressed with the *
assignment-suppression character" could be correct for the glibc
implementation, which is free to define behavior that's left
undefined by the standard (though it would have been nice to
mention that it's doing so). I don't know what Corrigendum it's
talking about. The use of the singular could imply that the man
page was written when TC1 was the only Corrigendum available,
but TC1 has nothing relevant.
The apparently incorrect wording is still in the latest version of
the man page at http://www.kernel.org/doc/man-pages/. I'll submit
an error report.
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Keith, you restored my faith in common sense. Special thanks for doing
so, and for the link to the standards paper.
Cheers,
pearly
> Here's the relevent part of the scanf(3) man page on my system, probably
> the same one juergen has:
>
> n Nothing is expected; instead, the number of characters
> consumed thus far from the input is stored through the
> next pointer, which must be a pointer to int. This is not
> a conversion, although it can be suppressed with the *
> assignment-suppression character. The C standard says:
> "Execution of a %n directive does not increment the
> assignment count returned at the completion of execution"
> but the Corrigendum seems to contradict this. Probably it
> is wise not to make any assumptions on the effect of %n
> conversions on the return value.
>
> Here's the description from N1256 7.19.6.2p12 (there are no change
> bars, so none of the three Corrigenda appear to have addressed this):
>
> n No input is consumed. The corresponding argument shall be
> a pointer to signed integer into which is to be written
> the number of characters read from the input stream so
> far by this call to the fscanf function. Execution of a %n
> directive does not increment the assignment count returned
> at the completion of execution of the fscanf function. No
> argument is converted, but one is consumed. If the conversion
> specification includes an assignment-suppressing character
> or a field width, the behavior is undefined.
>
[...]
> I don't know what Corrigendum it's
> talking about. The use of the singular could imply that the man
> page was written when TC1 was the only Corrigendum available,
> but TC1 has nothing relevant.
It's talking about C90 TC1, which added the statement "No argument is
converted, but one is consumed."
> The apparently incorrect wording is still in the latest version of
> the man page at http://www.kernel.org/doc/man-pages/. I'll submit
> an error report.
It's probably been in there for 15 years. About time it was fixed :-)
--
Geoff Clare <net...@gclare.org.uk>
I'm not sure I knew there was a C90 TC1. Is it available online?
[...]
> I'm not sure I knew there was a C90 TC1. Is it available online?
http://www.open-std.org/jtc1/sc22/wg14/www/docs/tc1.htm
and C90 TC2 is at
http://www.open-std.org/jtc1/sc22/wg14/www/docs/tc2.htm
--
Geoff Clare <net...@gclare.org.uk>