Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Using &array with scanf

Reply
Thread Tools

Using &array with scanf

 
 
James Daughtry
Guest
Posts: n/a
 
      01-05-2006
char array[20];
scanf("%19s", &array);

I know this is wrong because it's a type mismatch, where scanf expects
a pointer to char and gets a pointer to an array of 20 char. I know
that question 6.12 of the C FAQ says that it's wrong for that very
reason. What I don't know is where the standard tells me conclusively
that it's wrong. What I also don't know is somewhere that this type
mismatch will break in practice.

A peer asked me recently why it was wrong when I told him that it was
wrong, and I was very uncomfortable because I know it's wrong and I had
no good answer when he asked me to prove it. So how do I prove
something this to an exceptionally stubborn programmer who wants to
have black and white proof as well as a real example that fails?

Thanks!

 
Reply With Quote
 
 
 
 
Richard Heathfield
Guest
Posts: n/a
 
      01-05-2006
James Daughtry said:

> char array[20];
> scanf("%19s", &array);
>
> I know this is wrong because it's a type mismatch, where scanf expects
> a pointer to char and gets a pointer to an array of 20 char.


Yup. It's also wrong because it doesn't check the return value of scanf.

> I know that question 6.12 of the C FAQ says that it's wrong for that very
> reason.


Yup.

> What I don't know is where the standard tells me conclusively that it's
> wrong.


The fscanf specification:

s Matches a sequence of non-white-space characters. The corresponding
argument shall be a pointer to the initial character of an array large
enough to accept the sequence and a terminating null character, which
will be added automatically.

&array is not a pointer to the initial character of an array large enough to
accept the sequence; it's a pointer to an entire array. Different type.
That's a violation of a "shall" outside a constraint, so the behaviour is
undefined.

> What I also don't know is somewhere that this type
> mismatch will break in practice.


Irrelevant. A conforming implementation which breaks it could be released
tomorrow.

> A peer asked me recently why it was wrong when I told him that it was
> wrong, and I was very uncomfortable because I know it's wrong and I had
> no good answer when he asked me to prove it.


Ask him to explain how he can possibly confuse a char (*)[20] and a char *,
given that they are completely different types with completely different
sizes.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
 
Reply With Quote
 
 
 
 
Roland Csaszar
Guest
Posts: n/a
 
      01-05-2006
Hi,

At 5 Jan 2006 05:12:32 -0800,
James Daughtry wrote:
>
> char array[20];
> scanf("%19s", &array);
>
> A peer asked me recently why it was wrong when I told him that it was
> wrong, and I was very uncomfortable because I know it's wrong and I had
> no good answer when he asked me to prove it.


&array is a pointer to the pointer to the first element of array, it is
of type char**, not char*.
You can use
scanf ("%19s", array);
or
scanf ("%19s", &array[0]);


Regards,
Roland
--
Roland Csaszar ----------- \\\ /// -------------- +43 316 495 2129
Software Development ------ \\\ /// ----------- http://www.knapp.com
KNAPP Logistics Automation - \\V// - (E-Mail Removed)
 
Reply With Quote
 
James Daughtry
Guest
Posts: n/a
 
      01-05-2006
Richard Heathfield wisely wrote:
> James Daughtry said:
>
> > char array[20];
> > scanf("%19s", &array);
> >
> > I know this is wrong because it's a type mismatch, where scanf expects
> > a pointer to char and gets a pointer to an array of 20 char.

>
> Yup. It's also wrong because it doesn't check the return value of scanf.
>


Yea, I didn't want to dilute the example with error checking.
Fortunately, I have no intention of compiling that snippet, and I don't
imagine it will do any harm when executed as a Usenet post.

> > I know that question 6.12 of the C FAQ says that it's wrong for that very
> > reason.

>
> Yup.
>
> > What I don't know is where the standard tells me conclusively that it's
> > wrong.

>
> The fscanf specification:
>
> s Matches a sequence of non-white-space characters. The corresponding
> argument shall be a pointer to the initial character of an array large
> enough to accept the sequence and a terminating null character, which
> will be added automatically.
>
> &array is not a pointer to the initial character of an array large enough to
> accept the sequence; it's a pointer to an entire array. Different type.
> That's a violation of a "shall" outside a constraint, so the behaviour is
> undefined.
>


Ah, now that's my problem. I made a beeline to that very paragraph to
prove my point, and the result was a quickie program much like the
following. He was trying to tell me through the output of the program
that array and &array result in the same address, and the type doesn't
matter because scanf will treat the same address like a pointer to
char, and the type mismatch is irrelevant.

#include <stdio.h>

int main(void)
{
char array[20];

printf("%p\n%p\n", (void*)&array, (void*)array);

return 0;
}

Like I said, he's a stubborn little bugger.

> > What I also don't know is somewhere that this type
> > mismatch will break in practice.

>
> Irrelevant. A conforming implementation which breaks it could be released
> tomorrow.
>


Unfortunately, he's the kind of person who uses the "it works for me"
argument. I know he's wrong, you know he's wrong, but he refuses to
admit that he's wrong until I can write a program that proves him
wrong.

> > A peer asked me recently why it was wrong when I told him that it was
> > wrong, and I was very uncomfortable because I know it's wrong and I had
> > no good answer when he asked me to prove it.

>
> Ask him to explain how he can possibly confuse a char (*)[20] and a char *,
> given that they are completely different types with completely different
> sizes.
>


I asking him almost the same question. I asked why it should work when
pointers of different types aren't required to have the same
representation even if they point to the same address, adding emphasis
by pointing out the relevant parts of the standard. Holding his ground,
he ran the program again and said that the addresses are the same, then
ran an incorrect scanf example to prove that it worked the way he
expected, and repeated that scanf will do an implicit conversion
internally.

> --
> Richard Heathfield
> "Usenet is a strange place" - dmr 29/7/1999
> http://www.cpax.org.uk
> email: rjh at above domain (but drop the www, obviously)


 
Reply With Quote
 
James Daughtry
Guest
Posts: n/a
 
      01-05-2006

Roland Csaszar wrote:
> &array is a pointer to the pointer to the first element of array, it is
> of type char**, not char*.


Actually, it's of type char (*)[20]. The address-of operation is one of
the three cases where an array name isn't converted to a pointer to the
first element of the array.

 
Reply With Quote
 
kaikai
Guest
Posts: n/a
 
      01-05-2006
"James Daughtry" <(E-Mail Removed)>
??????:(E-Mail Removed) roups.com...
> char array[20];
> scanf("%19s", &array);
>
> I know this is wrong because it's a type mismatch, where scanf expects
> a pointer to char and gets a pointer to an array of 20 char. I know
> that question 6.12 of the C FAQ says that it's wrong for that very
> reason. What I don't know is where the standard tells me conclusively
> that it's wrong. What I also don't know is somewhere that this type
> mismatch will break in practice.
>
> A peer asked me recently why it was wrong when I told him that it was
> wrong, and I was very uncomfortable because I know it's wrong and I had
> no good answer when he asked me to prove it. So how do I prove
> something this to an exceptionally stubborn programmer who wants to
> have black and white proof as well as a real example that fails?
>
> Thanks!
>


scanf does not (also, could not) read arguments by their real type, that why
it
need a format string. All arguments will be reinterpreted from its value.
Since
array and &array do have the same value, the scanf function will produce
same
results. It is okay to write such code, but you'd better remember that it is
a
hack way.

kaikai



 
Reply With Quote
 
Ivan Budiselic
Guest
Posts: n/a
 
      01-05-2006
"James Daughtry" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed) oups.com...
> Richard Heathfield wisely wrote:
>> > A peer asked me recently why it was wrong when I told him that it was
>> > wrong, and I was very uncomfortable because I know it's wrong and I had
>> > no good answer when he asked me to prove it.

>>
>> Ask him to explain how he can possibly confuse a char (*)[20] and a char
>> *,
>> given that they are completely different types with completely different
>> sizes.
>>

>
> I asking him almost the same question. I asked why it should work when
> pointers of different types aren't required to have the same
> representation even if they point to the same address, adding emphasis
> by pointing out the relevant parts of the standard. Holding his ground,
> he ran the program again and said that the addresses are the same, then
> ran an incorrect scanf example to prove that it worked the way he
> expected, and repeated that scanf will do an implicit conversion
> internally.
>


You can't prove something beyond proving it The simple fact that the
standard renders the behavior undefined is certainly proof enough that it's
plain wrong. As far as the C language is concerned, there is no "work" and
"not work", or "correct" and "incorrect" once you enter the domain of UB.
Anything at all can happen, including something that someone might think is
"correct" (but, as I said before, there is no "correct", so he's wrong again


There really is no point in trying to go beyond a simple quote to the
relevant paragraphs of the standard.

--
Ivan Budiselic
ICQ# 104044323
IRC: buda @ #gamer.hr@quakenet
remove 'remove' for reply


 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      01-05-2006
James Daughtry said:

> Richard Heathfield wisely wrote:
>>
>> &array is not a pointer to the initial character of an array large enough
>> to accept the sequence; it's a pointer to an entire array. Different
>> type. That's a violation of a "shall" outside a constraint, so the
>> behaviour is undefined.
>>

>
> Ah, now that's my problem. I made a beeline to that very paragraph to
> prove my point, and the result was a quickie program much like the
> following. He was trying to tell me through the output of the program
> that array and &array result in the same address,


But they don't. What they result in is [SFX - takes huge breath] a sequence
of printable characters which, were it read back into scanf using a %p
format specifier, would allow the retrieval of a pointer value which would
refer to the same object as originally pointed to by the pointer value
passed to printf.

> and the type doesn't
> matter because scanf will treat the same address like a pointer to
> char,


The Standard does not say this will happen, so what makes your friend so
sure?

> and the type mismatch is irrelevant.


On the contrary, the type mismatch means the behaviour is undefined.

> #include <stdio.h>
>
> int main(void)
> {
> char array[20];
>
> printf("%p\n%p\n", (void*)&array, (void*)array);


This program doesn't actually demonstrate anything useful.

> Unfortunately, he's the kind of person who uses the "it works for me"
> argument.


Well, there's a certain amount to be said for such an argument! But I fail
to see what it gains him. He acknowledges that scanf requires a char *, and
he knows he's passing a char (*)[20] instead. He knows that omitting the &
is a simple enough operation which will make the code squeaky-clean, and
which is quicker to type than the wrong version. So he must have some very
powerful motivation for typing that &. Perhaps you would do better to ask
him what the & wins that pays for the type-wrongness of the code.

Please note that the "it means I don't have to worry about whether to put an
& on the front" is not a good-enough reason, because there are plenty of
cases where it matters a lot whether char * or char (*)[] is supplied (not
least when we start messing about with multi-dimensional arrays in argument
expressions), so he can't just think "always use a &"; as a paradigm it
doesn't work.

So - what does being wrong /buy/ him? Let him answer that.

> he ran the program again and said that the addresses are the same, then
> ran an incorrect scanf example to prove that it worked the way he
> expected, and repeated that scanf will do an implicit conversion
> internally.


What a trusting soul he is. Does he really think undefined behaviour will
manifest its nastiness at the most convenient moment for /him/? Hah! It
lurks. It waits in the background. It bides its time. And, when your boss
is proudly looking on as you demo the code to your best customer...

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
 
Reply With Quote
 
Richard Heathfield
Guest
Posts: n/a
 
      01-05-2006
kaikai said:

> Since
> array and &array do have the same value,


But they don't. The values have different types, so how can they be the
same?

Are $3.14 and 3.14kg the same? Of course not.
Are 3.14% and 3.14km the same? Of course not.

The type /matters/.

> It is okay to write such code,


No, it isn't.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
 
Reply With Quote
 
James Daughtry
Guest
Posts: n/a
 
      01-05-2006
Richard Heathfield wrote:
> James Daughtry said:
>
> > Richard Heathfield wisely wrote:
> >>
> >> &array is not a pointer to the initial character of an array large enough
> >> to accept the sequence; it's a pointer to an entire array. Different
> >> type. That's a violation of a "shall" outside a constraint, so the
> >> behaviour is undefined.
> >>

> >
> > Ah, now that's my problem. I made a beeline to that very paragraph to
> > prove my point, and the result was a quickie program much like the
> > following. He was trying to tell me through the output of the program
> > that array and &array result in the same address,

>
> But they don't. What they result in is [SFX - takes huge breath] a sequence
> of printable characters which, were it read back into scanf using a %p
> format specifier, would allow the retrieval of a pointer value which would
> refer to the same object as originally pointed to by the pointer value
> passed to printf.
>




> > and the type doesn't
> > matter because scanf will treat the same address like a pointer to
> > char,

>
> The Standard does not say this will happen, so what makes your friend so
> sure?
>


Good question.

> > and the type mismatch is irrelevant.

>
> On the contrary, the type mismatch means the behaviour is undefined.
>


To some people, "undefined" is just a word, and not even a scary word.
I'm sure that one day he'll get burned by UB and start to understand.
But until then, I have to work with the guy and suffer his "it works
for me" attitude.

> > #include <stdio.h>
> >
> > int main(void)
> > {
> > char array[20];
> >
> > printf("%p\n%p\n", (void*)&array, (void*)array);

>
> This program doesn't actually demonstrate anything useful.
>


That's what I thought. Sure, when he ran it the same two values were
printed, but it in no way proves that a type mismatch doesn't cause
problems.

> > Unfortunately, he's the kind of person who uses the "it works for me"
> > argument.

>
> Well, there's a certain amount to be said for such an argument! But I fail
> to see what it gains him. He acknowledges that scanf requires a char *, and
> he knows he's passing a char (*)[20] instead. He knows that omitting the &
> is a simple enough operation which will make the code squeaky-clean, and
> which is quicker to type than the wrong version. So he must have some very
> powerful motivation for typing that &. Perhaps you would do better to ask
> him what the & wins that pays for the type-wrongness of the code.
>
> Please note that the "it means I don't have to worry about whether to put an
> & on the front" is not a good-enough reason, because there are plenty of
> cases where it matters a lot whether char * or char (*)[] is supplied (not
> least when we start messing about with multi-dimensional arrays in argument
> expressions), so he can't just think "always use a &"; as a paradigm it
> doesn't work.
>
> So - what does being wrong /buy/ him? Let him answer that.
>


I'll ask, that's a very good question.

> > he ran the program again and said that the addresses are the same, then
> > ran an incorrect scanf example to prove that it worked the way he
> > expected, and repeated that scanf will do an implicit conversion
> > internally.

>
> What a trusting soul he is. Does he really think undefined behaviour will
> manifest its nastiness at the most convenient moment for /him/? Hah! It
> lurks. It waits in the background. It bides its time. And, when your boss
> is proudly looking on as you demo the code to your best customer...
>


Indeed. Thanks for your comments, they were very helpful.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
difference between scanf("%i") and scanf("%d") ??? perhaps bug inVS2005? =?ISO-8859-1?Q?Martin_J=F8rgensen?= C Programming 18 05-02-2006 10:53 AM
scanf (yes/no) - doesn't work + deprecation errors scanf, fopen etc. =?ISO-8859-1?Q?Martin_J=F8rgensen?= C Programming 185 04-03-2006 02:49 PM
Re: Can I detect "enter" key using scanf? bd C Programming 0 08-07-2003 02:03 AM
Re: Can I detect "enter" key using scanf? Dan Pop C Programming 0 08-06-2003 11:32 AM
Re: Can I detect "enter" key using scanf? Ben Pfaff C Programming 0 08-05-2003 09:49 PM



Advertisments