473,386 Members | 1,796 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

Using &array with scanf

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!

Jan 5 '06 #1
30 3132
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)
Jan 5 '06 #2
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// - mailto:ro************@knapp.com
Jan 5 '06 #3
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. :-P
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)


Jan 5 '06 #4

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.

Jan 5 '06 #5
"James Daughtry" <mo*******@hotmail.com>
??????:11*********************@z14g2000cwz.googleg 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

Jan 5 '06 #6
"James Daughtry" <mo*******@hotmail.com> wrote in message
news:11**********************@g49g2000cwa.googlegr 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
Jan 5 '06 #7
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)
Jan 5 '06 #8
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)
Jan 5 '06 #9
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.


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

Jan 5 '06 #10

"James Daughtry" <mo*******@hotmail.com> wrote in message
news:11**********************@g49g2000cwa.googlegr oups.com...
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


Someone who tries to prove program correctness (as defined by
the language standard) by using the behavior of a particular
implementation as evidence, is imo not really worthy of the
title 'programmer'.
that array and &array result in the same address,
Yes, the same 'value', but certainly not the same type.
Also note that while the 'value' might be the same,
the representation is not required to be the same.
and the type doesn't
matter

According to the standard, it *does* matter, very much.
because scanf will treat the same address like a pointer to
char,
Nowhere does the language standard make this assertion.
and the type mismatch is irrelevant.
It's *very* relevant, because it results in undefined behavior.

#include <stdio.h>

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

printf("%p\n%p\n", (void*)&array, (void*)array);
This is valid because the types of the arguments being passed
have been converted to types which *are* valid for specifier
'%p'

return 0;
}

Like I said, he's a stubborn little bugger.
Taking your description as valid, he seems to be to be
both ignorant and arrogant. Very dangerous combination.
I sincerely hope he's not involved in creating critical
software (e.g. that controlling hospital equipment, etc.).
> 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.


And I predict he'll be very surprised when suddenly it
ceases to work, and he has no idea why.
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. :-P
That's a losing battle. No program can prove him right or wrong,
since it's not implementations that define the language, but the
ISO standard document (ISO 9899).
> 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,

He can run it until doomsday, yet that will still prove nothing,
except perhaps a few things about a particular implementation.
then
ran an incorrect scanf example to prove that it worked the way he
expected,
That only proves that a particular implementation worked the
way he expected. It proves nothing at all about the correctness
of the code.

and repeated that scanf will do an implicit conversion
internally.


Ask him to cite from where a guarantee of such a conversion
comes. Certainly not from ISO 9899.

-Mike
Jan 5 '06 #11

"Roland Csaszar" <ro************@knapp.com> wrote in message
news:87lkxukdrr.wl%ro************@knapp.com...
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


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


Correct, since both expressions 'array' and '&array[0]'
yield the same type object.

-Mike
Jan 5 '06 #12
"James Daughtry" <mo*******@hotmail.com> writes:
Richard Heathfield wisely wrote:

[snip]
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.


scanf doesn't do a conversion, implicit or otherwise. It takes
whatever bits you give it and *assumes* that they constitute a valid
representation of an object of the correct type. There are
open-source/freeware implementations of scanf; ask him to show you the
code that does this "implicit conversion".

On a machine where hardware addresses point to words, it's plausible
that a byte pointer (char*) will have a different representation than
a word pointer (such as int*); a word pointer could be a machine
address, while a byte pointer could be a machine address plus an
offset specifying one byte within the word. (The C compilers on Cray
vector machines almost do this, but they put the offset into the
otherwise unused high-order bits of the word pointer.)

He ran the program again *on the same platform* and claimed that he
had proven that it works correctly. Pick a platform that he doesn't
have access to and ask him to "prove" that his code works correctly on
that platform.

Show him the following program:

#include <stdio.h>
int main(void)
{
int before[10];
int array[10];
int after[10];
array[-1] = array[10] = 42;
printf("array[-1] = %d\n", array[-1]);
printf("array[10] = %d\n", array[10]);
return 0;
}

You and I know that it invokes undefined behavior. On most systems,
I'd be surprised if the manifestation of that undefined behavior were
something other than producing the following output:

array[-1] = 42
array[10] = 42

Compile and run the program several times, showing him the consistent
output each time. Ask him if this "proves" that accessing elements
outside an array is valid.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 5 '06 #13
Roland Csaszar <ro************@knapp.com> writes:
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*.


Nope. Time to re-read section 6 of the comp.lang.c FAQ.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 5 '06 #14
Keith Thompson <ks***@mib.org> writes:
[snip]
He ran the program again *on the same platform* and claimed that he
had proven that it works correctly. Pick a platform that he doesn't
have access to and ask him to "prove" that his code works correctly on
that platform.


I suggest the IBM AS/400, especially if he's not familiar with it.
I'm not very familiar with it myself, but it seems to be a canonical
example of a system with a conforming C implementation that breaks a
lot of assumptions if you don't carefully stick to what the standard
actually guarantees; it's second only to the DS9K.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 5 '06 #15
In article <11**********************@g49g2000cwa.googlegroups .com>
James Daughtry <mo*******@hotmail.com> wrote:
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.
The problem with this argument lies in the phrase "the type mismatch
is irrelevant". That may be the case on *his* machine, but it is
definitely not the case on *every* machine.

There are machines (Burroughs A-series) in which integers are stored
in the same format as floating-point. (The compiler just makes sure
that the fractional part is always zero.) On such a machine, if you
do this:

double x;

ret = scanf("%d", (int *)&x);
if (ret == 1)
printf("I got %f\n", x);

the code actually works! But it fails on most machines, because the
type is *not* irrelevant on most machines.

For a machine on which the type matters, find a 1960s era PR1ME, or
perhaps even a 1980s Data General MV/10000 (aka Eclipse). (I am not
sure whether the type "pointer to array N of char" on the Eclipse
uses a word pointer, but if it does, the &array-with-scanf call will
in fact fail.)
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. :-P


If he is familiar with basketball, try the argument Steve Summit once
repeated here (I am not sure where he got it):

Someone told me that, in basketball, you have to bounce the
ball off the floor; you can't hold the ball and run around the
court. But I tried it and it works just fine. Obviously he
does not understand basketball!

Or, for Boston drivers, remember the rule about driving the wrong
way on a one-way street ("it's OK as long as you're in reverse!").
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jan 5 '06 #16
Richard Heathfield wrote:
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.


Just to illustrate that it's *not* okay to get sloppy with
types, here's an example that I discovered the other day.
#include <stdio.h>

char *t1 = "This can produce a segfault";
char t2[] = "Best to do it this way ....";

int
main (void)
{
int ia = 3, ib = 2;

/* no apparent problem (on my compiler) when I
* index into either string */
printf ("\nt1: '%s', 4th char: '%c'", t1, t1[ia]);
printf ("\nt2: '%s', 4th char: '%c'\n", t2, t2[ia]);

/* this is of course fine since we've declared
* the string is an array of char */
t2[ib] = t2[ia];
printf ("\nNo segfault here.\n");

/* this will produce a segfault with my compiler */
t1[ib] = t1[ia];
printf ("\nMaybe you'll get this far, but I don't.\n");

return 0;
}
One might think that "a string is a string is a string" --
that a pointer to a string is the same as the address of the
first char of an array of chars. It usually seems to work
this way, but the example above shows this isn't true.

--
"The secret of being boring is to say everything." - Voltaire
Jan 5 '06 #17
On 5 Jan 2006 05:40:08 -0800, in comp.lang.c , "James Daughtry"
<mo*******@hotmail.com> wrote:
Unfortunately, he's the kind of person who uses the "it works for me"
argument.


There's little point debating with such people. Give them the
information, explain exactly once why its incorrect to do it
otherwise, and walk away. If still they clean their gun while loaded,
eventually Darwin will come to your rescue.
Mark McIntyre
--

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jan 5 '06 #18
On 5 Jan 2006 09:36:23 -0800, in comp.lang.c , "James Daughtry"
<mo*******@hotmail.com> wrote:
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.


You could complain to your manager that his code is badly written and
potentially dangerous, pointing to the sections of the Standard which
are relevant. Even complete idiot managers tend to rely on
documentation and will accept that over "it works for me".....

Mark McIntyre
--

----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
Jan 5 '06 #19
eerok said:
Just to illustrate that it's *not* okay to get sloppy with
types, here's an example that I discovered the other day.
The example you give doesn't fail because of a type issue, but because you
attempt to write to storage that you're not supposed to write to. Had t1
been pointing at writeable storage, you'd have had no segfault. For
example, if you'd done this:
#include <stdio.h>

char *t1 = "This can produce a segfault";
char t2[] = "Best to do it this way ....";


char s[] = "This won't produce a segfault";
t1 = s;

you'd have had no problem, even though the type of t1 hasn't changed.

--
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)
Jan 5 '06 #20
Mark McIntyre <ma**********@spamcop.net> writes:
On 5 Jan 2006 05:40:08 -0800, in comp.lang.c , "James Daughtry"
<mo*******@hotmail.com> wrote:
Unfortunately, he's the kind of person who uses the "it works for me"
argument.


There's little point debating with such people. Give them the
information, explain exactly once why its incorrect to do it
otherwise, and walk away. If still they clean their gun while loaded,
eventually Darwin will come to your rescue.


Natural selection is very much like undefined behavior; there's no
reason to assume it will work to your benefit. The gun he's cleaning
is just as likely to be pointed at your head. More relevantly, you're
like to have to use the code he writes.

Elsethread, I suggested several possibilities for demonstrating that
the "it works for me" approach doesn't work. If *those* don't work,
he may be impervious to reason. Deciding when to give up and accept
this, either by walking away or by somehow preventing his bad code
from affecting anything, is left as an exercise.

But people can sometimes surprise you by turning around becoming
reasonable when you least expect it (see "undefined behavior").

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 6 '06 #21
In article <11**********************@g49g2000cwa.googlegroups .com> "James Daughtry" <mo*******@hotmail.com> writes:
....
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.
Note the difference:
char array[20];
scanf("%19s", &array);

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


Here &array and array are cast to (void *). So although originally
&array and array may have had different representations, after the
cast they are the some. So this proves exactly nothing. The original
would have been correct if you had written:
scanf("%19s", (char *)&array);
I do not know whether there are, or have been, machines that use different
representations for char pointers and pointers to an array of chars, but
it is conceivable.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Jan 6 '06 #22
In article <ln************@nuthaus.mib.org> Keith Thompson <ks***@mib.org> writes:
....
On a machine where hardware addresses point to words, it's plausible
that a byte pointer (char*) will have a different representation than
a word pointer (such as int*); a word pointer could be a machine
address, while a byte pointer could be a machine address plus an
offset specifying one byte within the word. (The C compilers on Cray
vector machines almost do this, but they put the offset into the
otherwise unused high-order bits of the word pointer.)


The C compiler for the Data General did precisely what you wrote. That
is, a byte pointer would have the byte address in all 32 bits, a word
pointer would have a word address in the lowest 31 bits. And in a byte
pointer the lowest bit indicates the byte in a word.

And on both implementations when c is a char pointer, (char *)(int *)c
may lose information. (Ever tried to implement the original source of
the Bourne shell on such a machine?)

On the other hand, on both implementations a pointer to an array of
chars can not be a word pointer. (There are no padding bytes
between elements of an array.) So on those implementations the
representation of char * and char *[20] is the same. Consider
char a[5][5],
&(a[1]) must be a pointer to the array starting at the fifth byte, and so
can not be a word pointer. And it is the fifth byte because there is no
padding.

But this does *not* say that the pointers can not have different
representations, although I do not know of a system where that is
indeed the case.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Jan 6 '06 #23
In article <dp*********@news2.newsguy.com> Chris Torek <no****@torek.net> writes:
....
For a machine on which the type matters, find a 1960s era PR1ME, or
perhaps even a 1980s Data General MV/10000 (aka Eclipse). (I am not
sure whether the type "pointer to array N of char" on the Eclipse
uses a word pointer, but if it does, the &array-with-scanf call will
in fact fail.)


See my other article. It can not use a word pointer for a pointer to
array N of char, because there is no padding between elements of
arrays.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Jan 6 '06 #24
"Dik T. Winter" <Di********@cwi.nl> writes:
[snip]
The C compiler for the Data General did precisely what you wrote. That
is, a byte pointer would have the byte address in all 32 bits, a word
pointer would have a word address in the lowest 31 bits. And in a byte
pointer the lowest bit indicates the byte in a word.

And on both implementations when c is a char pointer, (char *)(int *)c
may lose information. (Ever tried to implement the original source of
the Bourne shell on such a machine?)

On the other hand, on both implementations a pointer to an array of
chars can not be a word pointer. (There are no padding bytes
between elements of an array.) So on those implementations the
representation of char * and char *[20] is the same. Consider
char a[5][5],
&(a[1]) must be a pointer to the array starting at the fifth byte, and so
can not be a word pointer. And it is the fifth byte because there is no
padding.
You don't even have to resort to 2-dimensional arrays. Consider

char a[6];
typedef char (*array_ptr)[5];
array_ptr p0 = (array_ptr)a;
array_ptr p1 = (array_ptr)(a+1);

Both p0 and p1 are (I think!) valid pointers to arrays of 5 chars. p0
points to the array starting at element 0 of a; p1 points to the array
starting at element 1 of a (i.e., the last 5 of the 6 elements of a).
But this does *not* say that the pointers can not have different
representations, although I do not know of a system where that is
indeed the case.


Agreed. Even if they happen to have the same representation on all
possible platforms, I wouldn't find it particularly convenient to be
able to make that assumption.

Note that the code snippet above doesn't assume anything about the
representations of the various types of pointers. It uses casts
(explicit conversions), so the compiler will take care of any change
of representation necessary to convert from one pointer type to
another. The original question was about arguments to scanf, for
which no such conversion takes place.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 6 '06 #25
On 2006-01-06, Dik T. Winter <Di********@cwi.nl> wrote:
In article <dp*********@news2.newsguy.com> Chris Torek <no****@torek.net> writes:
...
> For a machine on which the type matters, find a 1960s era PR1ME, or
> perhaps even a 1980s Data General MV/10000 (aka Eclipse). (I am not
> sure whether the type "pointer to array N of char" on the Eclipse
> uses a word pointer, but if it does, the &array-with-scanf call will
> in fact fail.)


See my other article. It can not use a word pointer for a pointer to
array N of char, because there is no padding between elements of
arrays.


What about padding at the end of an array? Is a pointer to char
guaranteed to be convertible to a pointer to an array of chars?
Jan 6 '06 #26
Richard Heathfield wrote:
eerok said:
Just to illustrate that it's *not* okay to get sloppy with
types, here's an example that I discovered the other day.

The example you give doesn't fail because of a type issue, but because you
attempt to write to storage that you're not supposed to write to. Had t1
been pointing at writeable storage, you'd have had no segfault. For
example, if you'd done this:
#include <stdio.h>

char *t1 = "This can produce a segfault";
char t2[] = "Best to do it this way ....";


char s[] = "This won't produce a segfault";
t1 = s;

you'd have had no problem, even though the type of t1 hasn't changed.


Thanks for your response, which forced me to do some reading.
If my understanding is correct now, my problem was caused by
trying to write to a string literal, resulting in UB.

I'm trying to scrape the rust off my C skills, which were
learned long ago on a PDP-11 ... between the things I've
forgotten and the things that have changed, I'm pretty much a
newbie again :-)

--
"The secret of being boring is to say everything." - Voltaire

Jan 6 '06 #27
eerok said:
Thanks for your response, which forced me to do some reading.
If my understanding is correct now, my problem was caused by
trying to write to a string literal, resulting in UB.
Correct.
I'm trying to scrape the rust off my C skills, which were
learned long ago on a PDP-11 ... between the things I've
forgotten and the things that have changed, I'm pretty much a
newbie again :-)


You appear to learn reasonably quickly. Stick around clc, read more (much
more) than you write, and ask when you have to. If you do that, then within
a few months you should be sufficiently back up to speed to consider
answering questions here (which, if it can be done regularly without
getting your rear end handed to you on a platter, is almost enough to
qualify you as an "expert").

--
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)
Jan 6 '06 #28
In article <sl**********************@random.yi.org> Jordan Abel <ra*******@gmail.com> writes:
On 2006-01-06, Dik T. Winter <Di********@cwi.nl> wrote: ....
See my other article. It can not use a word pointer for a pointer to
array N of char, because there is no padding between elements of
arrays.


What about padding at the end of an array?


No. The size of an array is the product of the number of elements and
the size of an element.
Is a pointer to char
guaranteed to be convertible to a pointer to an array of chars?


I do not think it is guaranteed that way. It *is* guaranteed the
other way.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Jan 6 '06 #29
Richard Heathfield wrote:
eerok said:
[...]
I'm trying to scrape the rust off my C skills, which were
learned long ago on a PDP-11 ... between the things I've
forgotten and the things that have changed, I'm pretty much a
newbie again :-)

You appear to learn reasonably quickly. Stick around clc, read more (much
more) than you write, and ask when you have to. If you do that, then within
a few months you should be sufficiently back up to speed to consider
answering questions here (which, if it can be done regularly without
getting your rear end handed to you on a platter, is almost enough to
qualify you as an "expert").


Thanks, Richard. This newsgroup has been an enormous help to
me in the short time that I've been visiting here. Keep up
the good work :-)

--
"The secret of being boring is to say everything." - Voltaire

Jan 6 '06 #30
Chris Torek wrote:
If he is familiar with basketball, try the argument Steve Summit once
repeated here (I am not sure where he got it):

Someone told me that, in basketball, you have to bounce the
ball off the floor; you can't hold the ball and run around the
court. But I tried it and it works just fine. Obviously he
does not understand basketball!
That was Roger Miller, in <1994Jan31.125725.5553@verifone>.
Or, for Boston drivers, remember the rule about driving the wrong
way on a one-way street ("it's OK as long as you're in reverse!").


I suppose you think that's some kind of joke! Until recently,
I lived on a quiet one-way residential street in Cambridge,
and I saw people doing that all the time... :-)
Jan 11 '06 #31

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Rvenkatesh | last post by:
How to use array string in C#.Net to compare and replace characters between strings using function.
5
by: Oeleboele | last post by:
OK, I can't understand this exactly: I have this function: int howdy(void *) I first past this to the function &aCharArray I realized later that this should be aCharArray but... the former...
6
by: obdict | last post by:
Hello, I used scanf() in a while loop, which ensures that user input is valid (must be an integer no greater than 21 or less than 3). If user enters a number out of the range, or enters...
1
by: nel | last post by:
hi.. i want to know how to insert data using array in mysql where the data stored in field given? this field_name i taken from database.... thanks a lot...
2
by: palani12kumar | last post by:
Hi i've implemented a linear Queue using array. But i've been struck up with a doubt!!!!! Let me tell my problem with an example so that it can be clear. Size of the Queue(array) is 5. im...
1
shoonya
by: shoonya | last post by:
i am using array as a data type in my db .... ( sequence integer ) ; and it stores a value let {1,2,3,4,5}
2
by: berrylthird | last post by:
This question was inspired by scripting languages such as JavaScript. In JavaScript, I can access members of a class using array syntax as in the following example: var myInstance:myClass = new...
5
by: ryuchi311 | last post by:
In C++ using arrays. I need to create a C Program that will ask for five integers input from the user, then store these in an array. Then I need to find the lowest and highest integers inside that...
3
by: theprofoundgeek | last post by:
Hi, I am writing a C code to add two matrices. I want to take input with a feel of real martice, some thing like 1 2 3 4 5 6 7 8 9 but the Scanf function automatically enter EOL and hence...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.