Order of Variable Declartion

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???

Advertisements

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???

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.

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.

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???

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!

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.

" %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.

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.
>

> > 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 <> 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

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) 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.

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

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.

"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.

"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.

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!