HOW this program is executing plz explain the program

M

manish sahu

#include<stdio.h>
#include<conio.h>

main()
{
int i,j;

clrscr();
scanf("%d%d"+scanf("%d%d",&i,&j));
printf("%d %d",i,j);
getch();
return 0;
}
 
S

santosh

manish said:
#include<stdio.h>
#include<conio.h>

main()
{
int i,j;

clrscr();
scanf("%d%d"+scanf("%d%d",&i,&j));
printf("%d %d",i,j);
getch();
return 0;
}

The program above is broken. Firstly conio.h and the functions
clrscr() and getch() are not standard functions, but that's a minor
issue. Even if all three are commented out, your program is still
broken.

The single argument to the first scanf() call invokes undefined
behaviour, as it attempts to add an arbitrary int value (the return
value of the second scanf() call) to the pointer value to the first
character of a string literal. Adding integer values to a pointer
value is not defined in standard C, but even assuming it results in
simply another pointer value, the problem is now you're supplying a
pointer value to an unknown region of memory, which may or may not
contain a sensible format string for scanf() to interpret. It may not
even contain a sensible string. If scanf() does encounter any format
specifiers, it will attempt to perform the indicated conversion, but
you don't supply scanf() any storage locations to store them in.

It's just completely messed up. Don't learn from such code. You can't
learn anything sensible from poking at it. Learn proper C from a good
book.
 
J

jacob navia

santosh a écrit :
Adding integer values to a pointer
value is not defined in standard C,

WHAT??????

Please santosh!!


You should write ON HUNDRED TIMES

"I should turn on my brain before posting"

PointerValue+integer --> PointerValue+integer*element_size-->new pointer value!!!
 
S

santosh

jacob said:
santosh a �crit :

WHAT??????

Please santosh!!


You should write ON HUNDRED TIMES

"I should turn on my brain before posting"

PointerValue+integer --> PointerValue+integer*element_size-->new pointer value!!!

Right. Sincere apologies to the OP. I was thinking about conversion of
integer value to a pointer value.
 
J

jacob navia

santosh a écrit :
Right. Sincere apologies to the OP. I was thinking about conversion of
integer value to a pointer value.

Yes, the rest of your post seemed OK.
Anyway this can happen to anyone.

jacob
 
S

Seebs

The single argument to the first scanf() call invokes undefined
behaviour, as it attempts to add an arbitrary int value (the return
value of the second scanf() call) to the pointer value to the first
character of a string literal. Adding integer values to a pointer
value is not defined in standard C, but even assuming it results in
simply another pointer value, the problem is now you're supplying a
pointer value to an unknown region of memory, which may or may not
contain a sensible format string for scanf() to interpret.

Actually, I don't think that's true.

The only way this can not yield a viable value is if an input failure
occurs before any conversion. Otherwise, it's going to be 0, 1, or 2,
yielding "%d%d", "d%d", or "%d", respectively.
It may not
even contain a sensible string. If scanf() does encounter any format
specifiers, it will attempt to perform the indicated conversion, but
you don't supply scanf() any storage locations to store them in.

And on at least some systems, that'll result by happy coincidence in it
getting the values of &i and &j left around from the previous call.

But it's still shitty code.

-s
 
K

Keith Thompson

manish sahu said:
#include<stdio.h>
#include<conio.h>

main()
{
int i,j;

clrscr();
scanf("%d%d"+scanf("%d%d",&i,&j));
printf("%d %d",i,j);
getch();
return 0;
}

This is better in the sense that it's more portable and doesn't do
rude things like clearing the screen, but it's still junk (I've
also improved the layout, corrected the declaration of main,
and added a new-line to the output).

#include <stdio.h>

int main(void)
{
int i, j;

scanf("%d%d" + scanf("%d%d", &i, &j));
printf("%d %d\n", i, j);
return 0;
}

The inner scanf call is evaluated first. It will attempt to read two
int values, as text, from stdin, and store them in i and j. Let's
assume this succeeds.

So far, we've consumed two strings representing int values from stdin,
stored them in i and j, and returned the value 2 from scanf.

Now the outer scanf call is equivalent to

scanf("%d%d" + 2);

which in turn is equivalent to

scanf("%d");

for reasons I can explain if anyone doesn't already understand it.

This reads another string representing an int value from stdin and
.... wait, what?

The format string specifies that you're reading an int value,
but no corresponding argument is provided, so we haven't specified
where to store it. Undefined behavior. In practice, it's likely
to store the third int value from stdin in the location pointed to
by whatever address happens to be in the memory location where the
second argument *would* have been.

If the inner scanf call fails, it can return either 1 or 0, yielding
a format string for the outer scanf of either "d%d" or "%d%d".
"d%d" requires a literal 'd' on input, followed by an int value;
"%d%d" requires two int values. In either case, the behavior
is undefined because of the lack of following arguments; even
if those arguments were provided, the failure is quietly ignored
since the program doesn't check the result of the outer scanf call.
Or if an input failure occurs before any conversion, it yields
the value of EOF, which is negative (-1 on most implementations),
resulting in yet another cause of undefined behavior.

On my system, when I feed this program "100 200 300" as input, the
output is "300 200". There's probably some argument to be made
that this is the most likely result, based on where arguments are
probably stored on the stack, but I won't waste my time constructing
such an argument.

Obfuscated code has its place. Things like this can be useful
as puzzles to demonstrate how well you really know the language.
*Wrong* obfuscated code can even be useful for similar reasons;
knowing what's incorrect and why is as important as knowing
how correct code behaves. But if someone proposed to include
something like this in production code, physical violence would not
be my immediate response, but it would be somewhere on the list.
(That last part is a joke ... mostly.)
 
A

Andrew Poelstra

#include<stdio.h>
#include<conio.h>

This is unnecessary and non-portable, but fortunately(?) the
functions you call from it(?) are also unnecessary so we can
just imagine away that header, your call to clrscr() and the
call to getch().

main() returns int. Writing that explicitly is clearer and
more future-proof:
int main(void)

The void is also more specific; in theory just int main() could
accept an arbritary number of arguments, so in C it is better to
say int main(void).
{
int i,j;

clrscr();
scanf("%d%d"+scanf("%d%d",&i,&j));

The first argument to scanf is "%d%d" + n, where n is calculated
as the return value of scanf(). If scanf reads both characters,
the return value will be 2 and the argument will be "%d%d" + 2,
or "%d". Now scanf() expects an int to go with that, and gets
none, so you have invoked Undefined Behavior.

That's the best case.

Worst case, the second scanf() gets no valid input and returns 0,
so the first scanf() is expecting /two/ integers as additional
arguments, so again you have Undefined Behavior.

In either case your program logic is traipsing over memory it
doesn't own, and anything can happen, including but not limited
to sending SIGWAKE to the demon daemon, who will draw demons
from your nose.
printf("%d %d",i,j);

By this point, who knows what's happening.
 
B

Barry Schwarz

#include<stdio.h>
#include<conio.h>

main()
{
int i,j;

clrscr();
scanf("%d%d"+scanf("%d%d",&i,&j));
printf("%d %d",i,j);
getch();
return 0;
}

Please put your question in the body of your post, even if it just
duplicates your subject.

The program works only if you are very careful with your inputs. In
other cases, it invokes undefined behavior which, among other things,
means there is no explanation.

The inner call to scanf accepts at most two integers. If you do not
enter two integers, at least one of the two integers printed has an
indeterminate value and evaluating it causes undefined behavior.

If you do enter two integers, they must be of the form
int_1 int_2 ??? <ENTER>
where the quantity and choice of white space characters are irrelevant
as long as there is one between the two integers and one after the
second integer. The ??? represent additional optional data which will
not be processed by this call to scanf. The use of the enter key
assumes you are using a keyboard but your system may have other
methods of determining that the input is complete.

scanf will stop processing the input at the first character that is
not part of int_2 and this character will be made available to the
next attempt to read from stdin. At this point, both i and j have
been set and scanf will return 2, indicating that two values were
successfully converted.

The argument of the outer call to scanf is a pointer value formed by
the pointer arithmetic expression. The left operand of the addition
operator is the address of the string literal which is stored in your
program as an unnamed static array of char. The array consists of the
five characters '%', 'd', '%', 'd', and '\0'. The address of this
array is the address of the first '%'. The right operand is the int
returned by scanf, which we are assuming is 2. The result of this
addition is the address of the second '%'. Therefore, the effective
argument passed to scanf is "%d".

Thus, the outer call to scanf will accept at most one integer. One of
the features of the %d conversion specifier is that it will skip over
white space looking for the start of the integer. Assuming you did
not enter any ??? data, it will skip over all the white space
following int_2, including the '\n' generated by the enter key. It
will then wait for you to enter more data. Presumably, you hit enter
again. But this is just more white space to ignore. At this point,
you must force end of file or enter a non-numeric character followed
by the enter key. Either of these actions will cause the conversion
to fail and scanf to return. You should have no trouble with the
remaining code.

If you enter any numeric data when scanf is waiting, or if you entered
a characters sequence starting with a number after int_2, then this
outer call to scanf will attempt to convert that data into an int
value and store it somewhere. That somewhere would be specified by
the next argument to scanf but there is no other argument. This also
results in undefined behavior.

In summary, the program may have worked but if it did so it is only
because you cleverly, or luckily, avoided all the pitfalls.

It is also possible that the program did not work properly but only
appeared to. Improper input during either call to scanf results in
undefined behavior. One of the more undesirable manifestations of
undefined behavior is to appear to do what is expected, this time.
 
K

Keith Thompson

Barry Schwarz said:
Please put your question in the body of your post, even if it just
duplicates your subject.

The program works only if you are very careful with your inputs. In
other cases, it invokes undefined behavior which, among other things,
means there is no explanation.

The program's behavior is undefined no matter how careful you are
with your inputs.

[...]
Thus, the outer call to scanf will accept at most one integer. One of
the features of the %d conversion specifier is that it will skip over
white space looking for the start of the integer. Assuming you did
not enter any ??? data, it will skip over all the white space
following int_2, including the '\n' generated by the enter key. It
will then wait for you to enter more data. Presumably, you hit enter
again. But this is just more white space to ignore. At this point,
you must force end of file or enter a non-numeric character followed
by the enter key. Either of these actions will cause the conversion
to fail and scanf to return. You should have no trouble with the
remaining code.

C99 7.19.6.2p2 (describing fscanf, but the same applies to scanf):

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

Note that the behavior is undefined if there are insufficient
arguments *for the format*, whether any attempt is made to store
values or not.

In practice, this is likely to be harmless, but an implementation
could attempt to access all the objects into which values might be
stored, perhaps for the purpose of detecting this kind of problem
before consuming any input.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top