我可以在glibc 的实现中vfscanf()
找到以下代码,(截至撰写本文时,链接文件中的第 589-607 行)的实现scanf()
调用:
if (skip_space || (fc != L_('[') && fc != L_('c')
&& fc != L_('C') && fc != L_('n')))
{
/* Eat whitespace. */
int save_errno = errno;
__set_errno (0);
do
/* We add the additional test for EOF here since otherwise
inchar will restore the old errno value which might be
EINTR but does not indicate an interrupt since nothing
was read at this time. */
if (__builtin_expect ((c == EOF || inchar () == EOF)
&& errno == EINTR, 0))
input_error ();
while (ISSPACE (c));
__set_errno (save_errno);
ungetc (c, s);
skip_space = 0;
}
input_error()
是#define
d 为:
#define input_error() do {
errval = 1;
if (done == 0) done = EOF;
goto errout;
} while (0)
errout
最后清理代码的标签在哪里。
所以看起来在调用之前errno
被设置为,旧值后来被替换,保持不变。但是,如果发生错误并且该语句执行(特别是,如果计算结果为,这就是在这种情况下发生的情况),看起来重置为其原始值的代码可能会被跳过。话虽这么说,条件只有在并且因此不为零时才为真,这显然不是这种情况,在这里,所以它可能与这段代码无关,但这是我唯一能看到被设置的地方到. 正如评论所暗示的那样,它本身确实与,并且可以设置为,初始化为0
inchar()
errno
if
inchar()
EOF
errno
errno == EINTR
errno
0
inchar()
errno
errno
inchar_errno
0
在第 223 行,因此也可能存在其他一些inchar_errno
未更新但仍被分配到的执行路径errno
。