Order of Variable Declartion

Discussion in 'C Programming' started by Interrupt, Jan 14, 2010.

  1. Interrupt

    Interrupt Guest

    Hi folks, I'm trying to teach myself C, I’m finding it pretty hard
    going!! Something’s don’t make sense- for example I’ve written a bit
    of code if I declare variable int a; at the start of variable
    declarations (in a watch window : the code doesn’t work because int a
    =0 always; ) But if I declare it last the code works ie what ever the
    user inputs???

    ************ Code *********************************************
    #include <stdio.h>
    #include <stdlib.h>
    int manipulate(int a,int box,char c);
    int main()
    {
    while(1)
    {
    // if I declare int a here code doesn’t work???????
    char c;
    int z;
    int box;
    int a; // when I declare it here it works ??????

    puts("enter an integer b");
    scanf("%d",&box);

    puts( " the integer value a");
    scanf("%d",&a);


    puts("Enter the type of manipulation Required,/,*,+,-.");
    scanf("%s",&c);

    z = manipulate( a, box, c);

    printf("the Answer is %d\n\n",z);
    }
    return 0;
    }
    ************************ Code
    **********************************************************************
    Interrupt, Jan 14, 2010
    #1
    1. Advertising

  2. Interrupt

    Nick Guest

    Interrupt <> writes:

    > Hi folks, I'm trying to teach myself C, I’m finding it pretty hard
    > going!! Something’s don’t make sense- for example I’ve written a bit
    > of code if I declare variable int a; at the start of variable
    > declarations (in a watch window : the code doesn’t work because int a
    > =0 always; ) But if I declare it last the code works ie what ever the
    > user inputs???


    That is a sure sign that something has gone horribly wrong in your code,
    and something is stamping on the space in memory that your variable is
    held in.

    > ************ Code *********************************************
    > #include <stdio.h>
    > #include <stdlib.h>
    > int manipulate(int a,int box,char c);
    > int main()
    > {
    > while(1)
    > {
    > // if I declare int a here code doesn’t work???????
    > char c;
    > int z;
    > int box;
    > int a; // when I declare it here it works ??????
    >
    > puts("enter an integer b");
    > scanf("%d",&box);
    >
    > puts( " the integer value a");
    > scanf("%d",&a);
    >
    >
    > puts("Enter the type of manipulation Required,/,*,+,-.");
    > scanf("%s",&c);


    And here's where it happens. You read a string (%s) but c is char.

    So even if the user only enters a single character, you will still read
    that character and an "end of string" marker character ('\0'). Notice
    that it's when you put 'a' next to 'c' in the declaration that it goes
    wrong.

    If your user enters "I'd like to multiply those two numbers together
    please Bob", heaven knows what will happen.

    You either need to scanf for a character, or create a suitable sized
    string buffer for the result. I'm not a great user (or fan) of scanf,
    so I'll leave detailed recommendations on that to others.

    > z = manipulate( a, box, c);
    >
    > printf("the Answer is %d\n\n",z);
    > }
    > return 0;
    > }
    > ************************ Code
    > **********************************************************************

    --
    Online waterways route planner | http://canalplan.eu
    Plan trips, see photos, check facilities | http://canalplan.org.uk
    Nick, Jan 14, 2010
    #2
    1. Advertising

  3. On 2010-01-14, Interrupt <> wrote:
    > Hi folks, I'm trying to teach myself C, I?m finding it pretty hard
    > going!! Something?s don?t make sense- for example I?ve written a bit
    > of code if I declare variable int a; at the start of variable
    > declarations (in a watch window : the code doesn?t work because int a
    >=0 always; ) But if I declare it last the code works ie what ever the
    > user inputs???
    >
    > ************ Code *********************************************
    > #include <stdio.h>
    > #include <stdlib.h>
    > int manipulate(int a,int box,char c);
    > int main()
    > {
    > while(1)
    > {
    > // if I declare int a here code doesn?t work???????
    > char c;
    > int z;
    > int box;
    > int a; // when I declare it here it works ??????
    >
    > puts("enter an integer b");
    > scanf("%d",&box);
    >
    > puts( " the integer value a");
    > scanf("%d",&a);
    >
    > puts("Enter the type of manipulation Required,/,*,+,-.");
    > scanf("%s",&c);


    Here is your problem. %s expects a pointer to an array of char of
    indefinite length. Since such a thing does not exist, I'm not sure
    why the specifier is allowed to be used this way. (If you were to
    use, say, %20s, it would expect a pointer to an array of 20 char.)

    BUT, you don't have, nor do you want, an array. You have a single
    char, and for that you need to use the %c specifier.

    %s can't tell if you've given it a proper array; it just assumes
    that you have, even though you actually handed it an address of
    a single char. So it happily writes '+' to c, '\n' to the byte
    after c, and '\0' to the byte after that. But since you don't
    own those bytes, anything could happen! In this case I think you
    are overwriting the value of a, or something like that, which is
    why your code appears not to work.

    I hope this helps. I tried to be concise but I don't think I did.

    >
    > z = manipulate( a, box, c);
    >
    > printf("the Answer is %d\n\n",z);
    > }
    > return 0;
    > }
    > ************************ Code
    > **********************************************************************
    Andrew Poelstra, Jan 14, 2010
    #3
  4. Interrupt <> wrote:
    > Hi folks, I'm trying to teach myself C, I’m finding it pretty hard
    > going!! Something’s don’t make sense- for example I’ve written a bit
    > of code if I declare variable int a; at the start of variable
    > declarations (in a watch window : the code doesn’t work because int a
    > =0 always; ) But if I declare it last the code works ie what ever the
    > user inputs???


    The problem isn't related to the variable 'a' (that's only a
    collateral damage) but to the fact that your variable 'c' is
    defined as a single char but you try to read a string into it:

    > ************ Code *********************************************
    > #include <stdio.h>
    > #include <stdlib.h>
    > int manipulate(int a,int box,char c);
    > int main()
    > {
    > while(1)
    > {
    > // if I declare int a here code doesn’t work???????
    > char c;
    > int z;
    > int box;
    > int a; // when I declare it here it works ??????


    > puts("enter an integer b");
    > scanf("%d",&box);


    > puts( " the integer value a");
    > scanf("%d",&a);



    > puts("Enter the type of manipulation Required,/,*,+,-.");
    > scanf("%s",&c);


    Here you tell scanf() with "%s" that '&c' is a pointer to an array
    of chars but 'c' is only a single char. And scanf() will try to
    write the string the user enters into this location. Since there
    isn't room enough it's going to overwrite some other unrelated data
    (e.g. your variable 'a' if it's in the way). If you just need a
    char use "%c" instead if "%s" - that tells scanf() that you only
    expect a single char.

    Obviously your compiler organizes the variables in an order
    that, when you define 'a' before 'c', 'a' is located shortly
    after 'c' in memory and thus writing past 'c' overwrites what
    is stored in 'a'. But note that it could also the other way
    round, the compiler is free to decide where to put the vari-
    ables. And if you define 'a' after 'c' it may seem as if it
    works, but that's pure bad luck, you're then just overwriting
    some other (perhaps in this special case less essential) data.

    Just a warning: using scanf() to read strings with a simple "%s"
    is always dangerous since scanf() has no idea at all how much
    space there is for the string, and if the users enters a string
    that's longer than what would fit into the memory you set aside
    for it it, will happily write past the end of the array, resul-
    ting in a potentialy hard to find bug!

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, Jan 14, 2010
    #4
  5. Andrew Poelstra <> writes:

    > On 2010-01-14, Interrupt <> wrote:
    >> char c;

    <snip>
    >> puts("Enter the type of manipulation Required,/,*,+,-.");
    >> scanf("%s",&c);

    >
    > Here is your problem. %s expects a pointer to an array of char of
    > indefinite length. Since such a thing does not exist, I'm not sure
    > why the specifier is allowed to be used this way. (If you were to
    > use, say, %20s, it would expect a pointer to an array of 20 char.)
    >
    > BUT, you don't have, nor do you want, an array. You have a single
    > char, and for that you need to use the %c specifier.


    Beginners can get in a mess with %c because it does not skip white
    space and there will (probably) be some there from the previous
    numeric input.

    To the OP: if you switch to %c put a space in front like this:

    scanf(" %c", &c);

    The space is another input directive and means "skip white space
    characters".

    > %s can't tell if you've given it a proper array; it just assumes
    > that you have, even though you actually handed it an address of
    > a single char. So it happily writes '+' to c, '\n' to the byte
    > after c, and '\0' to the byte after that.


    Nit: %s stops on white space so it will only write '+' followed by
    '\0' when the '\n' is seen. The '\n' is left for the next input
    operation to see.

    Second to the OP: you really should be testing the return from scanf.
    It is a great habit to get into, not because it is the right thing to
    do (though it is) but because it gets you thinking about how the
    program should be shaped to cope with thing going wrong. Coping with
    things going wrong is one of the most important things to pick up, and
    you can't start too early.

    <snip>
    --
    Ben.
    Ben Bacarisse, Jan 14, 2010
    #5
  6. Richard Heathfield <> writes:

    > Interrupt wrote:

    <snip>
    >> scanf("%s",&c);

    >
    > Here's your problem. The easiest fix is to change %s to %c.


    " %c" will be less confusing to a beginner.

    > I suggest taking a good long look at the fgets() function. Not the
    > broken, deprecated gets() function, but the good, solid, easy-to-use
    > fgets() function, which reads a string from a file (you can use stdin,
    > of course) into an array of char. Grab all your data that way, and
    > convert it into numbers (where necessary) once you've got it safely
    > out of the input stream. And leave scanf until you've got a lot more
    > experience under your belt.


    Hmm... I'm not sure about this often quoted advice. scanf is fiddly,
    but so is line-based input and subsequent conversion. I agree that it
    is often better in the long-run, so it is worth getting to know that
    method, but I am not convinced that it is easier to /start/ doing
    input that way.

    --
    Ben.
    Ben Bacarisse, Jan 14, 2010
    #6
  7. On 2010-01-14, Ben Bacarisse <> wrote:
    >
    > ...
    >
    > Nit: %s stops on white space so it will only write '+' followed by
    > '\0' when the '\n' is seen. The '\n' is left for the next input
    > operation to see.
    >


    That's more than a nit - I didn't know that and it probably would
    have nailed me! (If I were ever to use scanf() on stdin.)

    > Second to the OP: you really should be testing the return from scanf.
    > It is a great habit to get into, not because it is the right thing to
    > do (though it is) but because it gets you thinking about how the
    > program should be shaped to cope with thing going wrong. Coping with
    > things going wrong is one of the most important things to pick up, and
    > you can't start too early.
    >


    That one I knew, but forgot to mention.
    Andrew Poelstra, Jan 14, 2010
    #7
  8. Interrupt

    Interrupt Guest


    > > Second to the OP: you really should be testing the return from scanf.
    > > It is a great habit to get into, not because it is the right thing to
    > > do (though it is) but because it gets you thinking about how the
    > > program should be shaped to cope with thing going wrong.  Coping with
    > > things going wrong is one of the most important things to pick up, and
    > > you can't start too early.


    Hi folks thanks to the many replies very helpful !! As you’ll have
    noticed I’m only starting so excuse my ignorance, how do you test the
    return from scanf??
    Interrupt, Jan 16, 2010
    #8
  9. Interrupt <> wrote:

    > > > Second to the OP: you really should be testing the return from scanf.
    > > > It is a great habit to get into, not because it is the right thing to
    > > > do (though it is) but because it gets you thinking about how the
    > > > program should be shaped to cope with thing going wrong.  Coping with
    > > > things going wrong is one of the most important things to pick up, and
    > > > you can't start too early.


    > Hi folks thanks to the many replies very helpful !! As you’ll have
    > noticed I’m only starting so excuse my ignorance, how do you test the
    > return from scanf??


    The return value tells you how many items scanf() found in the
    input. Normally you want as many as you asked for, e.g. if you
    have

    scanf( "%d %d %d", &x, &y, &z );

    then you should check if scanf() returned 3, i.e.

    if ( scanf( "%d %d %d", &x, &y, &z ) != 3 ) {
    fprintf( stderr, "Expected 3 int's but didn't find as many\n" );
    exit( EXIT_FAILURE );
    }

    Or, if the return value is 2, then you know that 'z' hasn't been
    set by the call of scanf() and thus it's not be safe to use its
    value (unless it had been set to a sane default value before).

    In your case, where you expect a single char, scanf() returns 1
    on success - but if it returns 0 then the user didn't enter a
    character (perhaps just hit the return key) and thus you should
    e.g. ask again.
    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, Jan 16, 2010
    #9
  10. (Jens Thoms Toerring) writes:
    <snip>
    > In your case, where you expect a single char, scanf() returns 1
    > on success - but if it returns 0 then the user didn't enter a
    > character (perhaps just hit the return key) and thus you should
    > e.g. ask again.


    It is not obvious how scanf("%c", &c) could return 0 in any normal
    use. If there is no more input or an input error occurs, scanf
    returns EOF. Otherwise a character (any character) is read and
    assigned. Obviously, if the behaviour is undefined because, for
    example, c is a float not a char then anything could happen (including
    a zero return).

    In particular, if the next character is a new line it will be read and
    scanf will return 1.

    --
    Ben.
    Ben Bacarisse, Jan 16, 2010
    #10
  11. Richard Heathfield <> wrote:
    > Jens Thoms Toerring wrote:
    > <snip>


    > >
    > > scanf( "%d %d %d", &x, &y, &z );
    > >
    > > then you should check if scanf() returned 3, i.e.
    > >
    > > if ( scanf( "%d %d %d", &x, &y, &z ) != 3 ) {
    > > fprintf( stderr, "Expected 3 int's but didn't find as many\n" );
    > > exit( EXIT_FAILURE );
    > > }
    > >
    > > Or, if the return value is 2, then you know that 'z' hasn't been
    > > set by the call of scanf() and thus it's not be safe to use its
    > > value (unless it had been set to a sane default value before).


    > It is not clear to me from the Standard whether it is safe to rely on
    > 'z''s value in such a circumstance even if you did set it to a sane
    > default value before the call.


    Probably an unwarranted assumption, based on hopeful thinking;-)
    And I also forgot to mention that scanf() may also return EOF
    (a negative number, often -1) on input failure before anything
    could be read (e.g. due to the user closing in the input chan-
    nel).
    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
    Jens Thoms Toerring, Jan 16, 2010
    #11
  12. Interrupt

    osmium Guest

    io_x wrote:

    > "Interrupt" <> ha scritto nel messaggio
    > news:...
    > Hi folks, I'm trying to teach myself C, I'm finding it pretty hard
    > going!! Something's don't make sense- for example I've written a bit
    > of code if I declare variable int a; at the start of variable
    > declarations (in a watch window : the code doesn't work because int a
    > =0 always; ) But if I declare it last the code works ie what ever the
    > user inputs???
    >
    > ************ Code *********************************************
    > what about: (don't know if it is right)
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <ctype.h>
    > #define P printf
    > #define F for
    > #define u8 unsigned char
    >
    > int manipulate(int a, int box, char c)
    > {P("Here enter: (a, box, char) == %d %d %c\n",
    > a, box, c);
    > return 0;
    > }
    >
    > int main()
    > {
    > while(1)
    > {int z;
    > int box;
    > int a; // when I declare it here it works ??????
    > char v[1024], c, *pc;
    >
    > puts( " the integer value a");
    > *v=0; pc=fgets(v, 1024, stdin);
    > if(pc==0) break;
    > z=sscanf(v, "%d",&a);
    > if(z!=1) break;
    >
    > puts("enter an integer b");
    > *v=0; pc=fgets(v, 1024, stdin);
    > if(pc==0) break;
    > z=sscanf(v, "%d", &box);
    > if(z!=1) break;
    >
    > puts("Enter the type of manipulation Required,/,*,+,-.");
    > *v=0; pc=fgets(v, 1024, stdin);
    > if(pc==0) break;
    > F(z=0; z<1024&&v[z]; ++z)
    > if(!isspace((u8) v[z])) break;
    > if(z==1024||v[z]==0) break;
    > c=v[z];
    > z=manipulate( a, box, c);
    > printf("the Answer is %d\n\n",z);
    > }
    >
    > return 0;
    > }
    >
    > for one game this code could be right
    > for other it is need to write down routines
    > that cach all errors (overflow, required "/*+-" etc etc


    Google strikes again. That message, as viewed on my newsreader is almost
    undecipherable. Caused by the fact that Interrupt is posting from Google
    with their cavalier standards WRT protocols.

    I see no attributions and this is a thread I haven't been following.
    Finally, after chasing through the history, I detected a three line message
    appended at the end.

    Damn those people at Google!
    osmium, Jan 16, 2010
    #12
  13. On Thu, 14 Jan 2010 21:24:28 GMT, Andrew Poelstra
    <> wrote:

    > On 2010-01-14, Interrupt <> wrote:


    > > char c;


    > > scanf("%s",&c);

    >
    > Here is your problem. %s expects a pointer to an array of char of
    > indefinite length. Since such a thing does not exist, I'm not sure


    Not really indefinite; just large enough for the actual (whitespace
    delimited) input value found. If you have sufficient control over or
    trust of your input data this might be right -- but that 'if' is often
    hard to maintain over time, which is why this is unwise.

    > why the specifier is allowed to be used this way. (If you were to
    > use, say, %20s, it would expect a pointer to an array of 20 char.)
    >

    21, to be safe. %Ns, and %N[charset], will store up to N input
    characters plus a null terminator. OTOTH %Nc will store only N
    characters, and fgets(buf,N,fp) will store up to N-1 chars including
    the newline (if found) plus a null for a total not exceeding N.

    Yes, this can be annoying.
    David Thompson, Jan 28, 2010
    #13
  14. Interrupt

    osmium Guest

    "James Harris - 1xf" wrote:

    > "osmium" <> wrote in message
    > news:...
    >> io_x wrote:
    >>
    >>> "Interrupt" <> ha scritto nel messaggio
    >>> news:...

    >
    > ...
    >
    >>
    >> Google strikes again. That message, as viewed on my newsreader is almost
    >> undecipherable. Caused by the fact that Interrupt is posting from Google
    >> with their cavalier standards WRT protocols.

    >
    > I've looked at the message you refer to in via three methods: Google,
    > x-privat web and x-privat via Outlook Express. It looks decipherable to me
    > in all three.
    >
    > That said, io_x's programming style is equally hard to read in all three
    > but that's due to his lack of spacing rather than any display issues.
    >
    >
    >
    >> I see no attributions and this is a thread I haven't been following.
    >> Finally, after chasing through the history, I detected a three line
    >> message appended at the end.

    >
    > Again, in all three options the message seems to me to be properly linked
    > into the thread. What reader are you using?


    I have no reason to think any link was bad. The problem is that my
    newsreader elides the leading '>' on certain messages from Google, thus the
    message and the response to it are just a jumble. Note that almost
    undecipherable doesn't mean the same thing as undecipherable. I use Outlook
    Express, there is a front end for it, called QuoteFix, that solves that
    problem but the (convenient) link provided from my browser leads to the
    basic OE. I probably used the QuoteFix version on my earlier response.

    I haven't studied this but someone once said Google posts HTML and Usenet is
    supposed to be plain text.
    osmium, Jan 29, 2010
    #14
  15. Interrupt

    osmium Guest

    "Richard Heathfield" wrote:

    > osmium wrote:
    >
    > <snip>
    >
    >> I haven't studied this but someone once said Google posts HTML and Usenet
    >> is supposed to be plain text.

    >
    > I *have* studied this. Using a tremendously significant statistical sample
    > of - um - one article, I conclude that Google doesn't *always* post HTML.
    > The one article I checked was plain text. The relevant header was:
    >
    > Content-Type: text/plain; charset=ISO-8859-1
    >
    > and the content was straight text. Not so much as an = in the whole
    > article body.


    Thanks much for the update! That is consistent with my finding that quoting
    a Google message only leads to problems part of the time. Bill Cunningham
    posts, for one, sometimes give me a problem, sometimes not. Maybe you can
    focus your follow on studies on him, assuming you get your grant of stimulus
    money.
    osmium, Jan 29, 2010
    #15
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Soren Kuula
    Replies:
    2
    Views:
    498
    Soren Kuula
    Feb 1, 2004
  2. mfglinux
    Replies:
    11
    Views:
    699
    Roberto Bonvallet
    Sep 12, 2007
  3. cspoh
    Replies:
    0
    Views:
    247
    cspoh
    Jul 31, 2003
  4. Stephan Kämper
    Replies:
    2
    Views:
    233
    Stephan Kämper
    Jan 18, 2004
  5. David Filmer
    Replies:
    19
    Views:
    240
    Kevin Collins
    May 21, 2004
Loading...

Share This Page