Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does sscanf touch pointers if no match has been found? [duplicate]

Tags:

c

scanf

If a line does not match a [fsv]scanf format, does scanf guarantee not to touch the provided pointers that are not matched?

For example, if

int int1 = 3;
int int2 = 5;
sscanf(line, "%d %d", &int1, &int2);

returns 0, are the integers guaranteed to be still 3 and 5, or can int1 have been changed?

like image 649
Peter Smit Avatar asked Sep 29 '14 10:09

Peter Smit


People also ask

Does sscanf move pointer?

You are correct: sscanf indeed does not "move", because there is nothing to move. If you need to scan a bunch of ints, you can use strtol - it tells you how much it read, so you can feed the next pointer back to the function on the next iteration.

How does sscanf work in assembly?

sscanf takes as arguments a string to scan, a format string, and pointers to variables where to store the results of the scan. So, your 0 and 1 numbers would be stored on the corresponding variables, assuming the scan was successful. EAX contains the return value.

What does %n do in sscanf?

In the case of printf() function the %n assign the number of characters printed by printf(). When we use the %n specifier in scanf() it will assign the number of characters read by the scanf() function until it occurs. Key points: It is an edit conversion code.

What is the difference between the scanf () and sscanf () functions?

The scanf function reads data from standard input stream stdin into the locations given by each entry in the argument list. The argument list, if it exists, follows the format string. The sscanf function reads data from buffer into the locations given by argument list.


Video Answer


1 Answers

The short answer is yes, in your case you can guarantee that int1 and int2 have not changed.

However, I would advise against relying on this behaviour, as it's likely to produce code that is difficult to read - and because:


The long answer is it depends on your format string. Looking at the C11 standard for fscanf (s7.21.6.2.16), we have:

The fscanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.

Critically important is this definition of input items from later in 7.21.6.2:

An input item is defined as the longest sequence of input characters which does not exceed any specified field width and which is, or is a prefix of, a matching input sequence

So. The number returned by scanf is the number of items read from the stream, not the number of pointers written to.

Additionally relevant is 7.21.6.2.2:

If the format is exhausted while arguments remain, the excess arguments are evaluated (as always) but are otherwise ignored.

The behaviour of ignoring arguments that aren't written to is also made explicit in an example at the end of that section:

In:

    #include <stdio.h>
    /* ... */
    int d1, d2, n1, n2, i;
    i = sscanf("123", "%d%n%n%d", &d1, &n1, &n2, &d2);

the value 123 is assigned to d1 and the value 3 to n1. Because %n can never get an input failure the value of 3 is also assigned to n2. The value of d2 is not affected. The value 1 is assigned to i.

In case you're not familiar with %n, it's "the number of characters read from the stream so far".

This is a great example to illustrate your question - here we have three pointers written to, and one pointer untouched. But, fscanf only returns 1 here - because it only assigned one "input item" from the stream.

So, in your example, yes, if you've got %d %d and you pass it something which causes 0 reads, then yes, the pointers will be untouched.

But, if you've got a %n in there, then your function could still return 0 or EOF while still consuming some input and writing to pointers. For example:

sscanf("aaa","aaa%n%d",&n1,&n2);

This writes 3 to n1, leaves n2 untouched, and returns EOF. And:

sscanf("aaa bbb","aaa%n%d",&n1,&n2);

This writes 3 to n1, leaves n2 untouched, and returns 0.

like image 175
Timothy Jones Avatar answered Nov 07 '22 14:11

Timothy Jones