scanf function and 2-d arrays

M

madhura

Hello,
I have a problem with 2-d arrays and scanf function.
I have wriitten a code in which i am accepting values in 1-d arrays
int a[5],i;
for(i=0;i<3;i++)
scanf("%d",a+i);
when I print the values, it showed me the correct values,but when i
wrote the same code for 2-d arrays,
int a[2][2],i,j;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
scanf("%d",a+i+j);
after printing,it showed me garbage values for a[0][1] and a[1][1], is
it because my compiler doesnt have the program for handling such
expressions.
why this happened, can anybody tell me,
cheers
madhura
 
P

pemo

madhura said:
Hello,
I have a problem with 2-d arrays and scanf function.
I have wriitten a code in which i am accepting values in 1-d arrays
int a[5],i;
for(i=0;i<3;i++)
scanf("%d",a+i);
when I print the values, it showed me the correct values,but when i
wrote the same code for 2-d arrays,
int a[2][2],i,j;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
scanf("%d",a+i+j);
after printing,it showed me garbage values for a[0][1] and a[1][1], is
it because my compiler doesnt have the program for handling such
expressions.
why this happened, can anybody tell me,
cheers
madhura

for(i=0;i<2;i++)
for(j=0;j<2;j++)
scanf("%d",&a[j]);

for(i=0;i<2;i++)
for(j=0;j<2;j++)
printf("%d\n",a[j]);

Consider the difference in the output of this ...

for(i=0;i<2;i++)
for(j=0;j<2;j++)
printf("%p\t%p\n",(void *)(a+i+j),(void *)(&a[j]));

Clearer?


--
===============================================================
In an attempt to reduce 'unwanted noise' on the 'signal' ...

Disclaimer:

Any comment/code I contribute might =NOT= be 100% portable, nor
semantically correct [read - 'not 100% pedantically correct'].
I don't care too much about that though, and I reckon it's the
same with most 'visitors' here. However, rest assured that any
'essential' (?) corrections WILL almost certainly appear v.soon
[read - 'to add noise as they see fit, *a pedant* will be along
shortly'].

WARNINGS: Always read the label. No beside-the-point minutiae
filter supplied. Keep away from children. Do not ignite.
===============================================================
 
V

Vladimir S. Oka

madhura said:
Hello,
I have a problem with 2-d arrays and scanf function.
I have wriitten a code in which i am accepting values in 1-d
arrays int a[5],i;
for(i=0;i<3;i++)
scanf("%d",a+i);
when I print the values, it showed me the correct values,but
when i wrote the same code for 2-d arrays,
int a[2][2],i,j;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
scanf("%d",a+i+j);

Have a think about this last line, and it may tell you where
your problem is. Is a[j] the same as *(a+i+j)?

Cheers

Vladimir
after printing,it showed me garbage values for a[0][1] and
a[1][1], is it because my compiler doesnt have the program for
handling such expressions.
why this happened, can anybody tell me,
cheers
madhura
 
A

Andrey Tarasevich

madhura said:
Hello,
I have a problem with 2-d arrays and scanf function.
I have wriitten a code in which i am accepting values in 1-d arrays
int a[5],i;
for(i=0;i<3;i++)
scanf("%d",a+i);
when I print the values, it showed me the correct values,but when i
wrote the same code for 2-d arrays,
int a[2][2],i,j;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
scanf("%d",a+i+j);
after printing,it showed me garbage values for a[0][1] and a[1][1], is
it because my compiler doesnt have the program for handling such
expressions.
why this happened, can anybody tell me,

If you insist on using '+' operator in order to perform index access to array
elements, then the corresponding expression for 2-dimensional array would look
as follows

*(a + i) + j

That would be equivalent to

&a[j]

which is what you need in your case (and why don't you just stick with that
latter form?).

As for the "why?" part, it has been explained here and elsewhere more than once.
You can start by looking up the corresponding section in the FAQ: http://c-faq.com.
 
C

CBFalconer

Andrey said:
.... snip ...

If you insist on using '+' operator in order to perform index
access to array elements, then the corresponding expression for
2-dimensional array would look as follows

*(a + i) + j

WRONG. You are thinking of arrays of pointers. You need to
incorporate the size of the first component of the array.
That would be equivalent to

&a[j]

which is what you need in your case (and why don't you just stick
with that latter form?).

As for the "why?" part, it has been explained here and elsewhere
more than once. You can start by looking up the corresponding
section in the FAQ: http://c-faq.com.


RIGHT.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
 
K

Keith Thompson

CBFalconer said:
WRONG. You are thinking of arrays of pointers. You need to
incorporate the size of the first component of the array.

It depends on how the array is declared. If it's an actual
two-dimensional array, the pointer arithmetic will take care of the
component sizes. For example:

#include <stdio.h>

int main(void)
{
int a[20][30];
int i = 5;
int j = 7;
int *x = *(a + i) + j;
int *y = &(a[j]);

if (x == y) {
printf("x == y\n");
}
else {
printf("x != y\n");
}
printf("x = %p\n", (void*)x);
printf("y = %p\n", (void*)y);

return 0;
}

Output (on one system I've tried):

x == y
x = 0x22e7d4
y = 0x22e7d4
 
C

Chris Torek

[which means the same as &a[j], although the latter is easier
to read]

WRONG. You are thinking of arrays of pointers. You need to
incorporate the size of the first component of the array.

Andrey Tarasevich is correct. When "a" has type T a[M][N] (for
suitable M and N), the above has the same meaning as a + j which
has the same meaning as &a[j]. In fact, even if "a" has type
T *a[N] or T (*a)[M] or T **a, it still works out the same way
(although in all these cases, the pointers themselves must be
made to point somewhere useful first).

The OP may also find <http://web.torek.net/torek/c/pa.html> helpful.
 
A

Andrey Tarasevich

CBFalconer said:
WRONG. You are thinking of arrays of pointers. You need to
incorporate the size of the first component of the array.

As others already noted, there's nothing wrong with the above expression. The
fact that '+'-based access looks syntactically the same for both arrays of
pointers and "regular" multidimensional arrays is something that some people
often find hard to believe at first. However, if you take a closer look at the
semantical meaning of the above expression in both cases you'll see that it
works for both.
 
C

CBFalconer

Andrey said:
As others already noted, there's nothing wrong with the above
expression. The fact that '+'-based access looks syntactically
the same for both arrays of pointers and "regular" multidimensional
arrays is something that some people often find hard to believe
at first. However, if you take a closer look at the semantical
meaning of the above expression in both cases you'll see that it
works for both.

My reasoning is that *(a + i) dereferences something, which needs
to be a pointer. After that the +j allows that pointer to aim
elsewhere. Meanwhile that pointer has to have been stored in the
array to allow it to be extracted and thence incremented.

Assume the declaration is: int a[XDIM][YDIM];

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
 
A

Andrey Tarasevich

CBFalconer said:
My reasoning is that *(a + i) dereferences something, which needs
to be a pointer.

That's correct.
After that the +j allows that pointer to aim
elsewhere. Meanwhile that pointer has to have been stored in the
array to allow it to be extracted and thence incremented.

Not necessaryly _stored_. There's another rather well-known source of
pointers in C expressions: implicit array-to-pointer conversion.
Assume the declaration is: int a[XDIM][YDIM];

OK. Let's do it step by step.

1) If we use this 'a' in the above expression, it will immediately decay
to pointer type, which is in this case 'int (*)[YDIM]'. The pointer
points to the first sub-array in the entire 2-dimensional array, i.e. to
a[0].

2) We add 'i' to the result of the decay. We get a pointer of type 'int
(*)[YDIM]' that points to a.

3) We dereference the pointer obtained at step 2 and get the i-th
subarray itself - an array value of type 'int[YDIM]'.

4) The array value obtained at step 3 immediately decays to pointer type
'int*'. The pointer points to the first element of i-th subarray, i.e.
to a[0].

5) We add 'j' to the result of the decay. We get a pointer of type
'int*' that points to a[j], which is exactly what we need.

If we try to do the same for "array of pointers" the sequence of steps
will look differently. This is not unexpected, since the semantical
meaning of the above expression depends on the type of 'a'. But in both
cases it _looks_ the same. And it works.
 
C

CBFalconer

Andrey said:
CBFalconer said:
My reasoning is that *(a + i) dereferences something, which needs
to be a pointer.

That's correct.
After that the +j allows that pointer to aim
elsewhere. Meanwhile that pointer has to have been stored in the
array to allow it to be extracted and thence incremented.

Not necessaryly _stored_. There's another rather well-known source
of pointers in C expressions: implicit array-to-pointer conversion.
Assume the declaration is: int a[XDIM][YDIM];

OK. Let's do it step by step.

1) If we use this 'a' in the above expression, it will immediately
decay to pointer type, which is in this case 'int (*)[YDIM]'. The
pointer points to the first sub-array in the entire 2-dimensional
array, i.e. to a[0].

2) We add 'i' to the result of the decay. We get a pointer of type
'int (*)[YDIM]' that points to a.

3) We dereference the pointer obtained at step 2 and get the i-th
subarray itself - an array value of type 'int[YDIM]'.

4) The array value obtained at step 3 immediately decays to pointer
type 'int*'. The pointer points to the first element of i-th
subarray, i.e. to a[0].

5) We add 'j' to the result of the decay. We get a pointer of type
'int*' that points to a[j], which is exactly what we need.

If we try to do the same for "array of pointers" the sequence of
steps will look differently. This is not unexpected, since the
semantical meaning of the above expression depends on the type of
'a'. But in both cases it _looks_ the same. And it works.


Alright, you convinced me. Even hoary old hound dogs can learn
some new tricks. But I wouldn't use it - IMO it is too obscure.
Thanks.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,173
Messages
2,570,937
Members
47,481
Latest member
ElviraDoug

Latest Threads

Top