HOW this program is executing plz explain the program

Discussion in 'C Programming' started by manish sahu, Feb 13, 2010.

  1. manish sahu

    manish sahu Guest

    #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;
    }
     
    manish sahu, Feb 13, 2010
    #1
    1. Advertisements

  2. manish sahu

    santosh Guest

    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.
     
    santosh, Feb 13, 2010
    #2
    1. Advertisements

  3. manish sahu

    jacob navia Guest

    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!!!
     
    jacob navia, Feb 13, 2010
    #3
  4. manish sahu

    santosh Guest

    Right. Sincere apologies to the OP. I was thinking about conversion of
    integer value to a pointer value.
     
    santosh, Feb 13, 2010
    #4
  5. manish sahu

    jacob navia Guest

    santosh a écrit :
    Yes, the rest of your post seemed OK.
    Anyway this can happen to anyone.

    jacob
     
    jacob navia, Feb 13, 2010
    #5
  6. manish sahu

    santosh Guest

    It would be interesting if the OP could tell us where he picked up
    this snippet and what the original author claims it to demonstrate.

    To the OP: The following link is a good tutorial to start learning C
    from:

    <http://www.eskimo.com/~scs/cclass/cclass.html>
     
    santosh, Feb 13, 2010
    #6
  7. manish sahu

    Seebs Guest

    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.
    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
     
    Seebs, Feb 13, 2010
    #7
  8. 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.)
     
    Keith Thompson, Feb 13, 2010
    #8
  9. 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).
    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.
    By this point, who knows what's happening.
     
    Andrew Poelstra, Feb 13, 2010
    #9
  10. 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.
     
    Barry Schwarz, Feb 13, 2010
    #10
  11. manish sahu

    Stefan Ram Guest

    This does something implementation-specified
    and then something undefined.
     
    Stefan Ram, Feb 13, 2010
    #11
  12. The program's behavior is undefined no matter how careful you are
    with your inputs.

    [...]
    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.
     
    Keith Thompson, Feb 13, 2010
    #12
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.