Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A test problem...

9 views
Skip to first unread message

John Baum

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to

I had this problem on a test in C recently, needless to say no one
got it right.

Why are each of the printed expressions equivalent?


/* INCLUDE FILES */
# include "stdio.h"
# include "stdlib.h"
# include "conio.h"

/* DATA DECLARATIONS */
int a[3][5];
int i=1;
int j=1;

main()
{
/* MAIN MODULE */
clrscr();

a[1][1]=25; // INITIALIZE

printf("\n 1=%d ",*(a[i]+j));
printf("\n 2=%d ",(*(a+i))[j]);
printf("\n 3=%d ",*((*(a+i))+j));
printf("\n 4=%d ",*(&a[0][0]+5*i+j));
printf("\n 5=%d ",a[i][j];
return(0);
}

John R Buchan (jatmon)

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
In article <40rrl8$q...@news.computek.net>, bom...@computek.net says...

>
>
>I had this problem on a test in C recently, needless to say no one
>got it right.
>
>Why are each of the printed expressions equivalent?
>
>
>/* INCLUDE FILES */
># include "stdio.h"
># include "stdlib.h"
># include "conio.h"
>
>/* DATA DECLARATIONS */
>int a[3][5];
>int i=1;
>int j=1;
>
>main()
> {
> /* MAIN MODULE */
> clrscr();
>
> a[1][1]=25; // INITIALIZE

So a now looks like:

<indexed>
a[0][0] a[1][1] a[2][4]
| | |
0 0 0 0 0 0 25 0 0 0 0 0 0 0 0
| |
&a[0][0] + 0 1 2 3 4 5 6 7 8 9 ...
<pointer + offset>

>
> printf("\n 1=%d ",*(a[i]+j));

a[i] == a[1] <resolves to an int pointer to a[1][0]> == &a[1][0],
&a[1][0] + j == &a[1][0] + 1 == &a[1][1],
*(&a[1][1]) == a[1][1] == 25

> printf("\n 2=%d ",(*(a+i))[j]);

a <resolves to a pointer to array of 5 ints> == &a[0],
&a[0] + i == &a[0] + 1 == &a[1],
*(&a[1]) == a[1],
a[1][j] == a[1][1] == 25

> printf("\n 3=%d ",*((*(a+i))+j));

*(a+i) == a[1] <see 2nd problem>,
a[1] + j == a[1] + 1 == &a[1][1] == 25 <see 1st problem>

> printf("\n 4=%d ",*(&a[0][0]+5*i+j));

5 * i + j == 5 * 1 + 1 == 6,
&a[0][0] <is equivalent to an int pointer to a[0][0]>,
&a[0][0] + 6 == &a[1][1] <6 ints from the beginning of the array>,
*(&a[1][1]) == a[1][1] == 25

> printf("\n 5=%d ",a[i][j];

a[i][j] == a[1][1] == 25

> return(0);
> }
>
>

I hope at least some of this ends up being coherent. As usual,
I'm up too late to be trying to think straight.

--
John R Buchan -:|:- Looking for that elusive FAQ? ftp to:
jat...@mail.iag.net -:|:- rtfm.mit.edu /pub/usenet-by-group/....


Lawrence Kirby

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
In article <40rrl8$q...@news.computek.net> bom...@computek.net "John Baum" writes:

>
>I had this problem on a test in C recently, needless to say no one
>got it right.

>Why are each of the printed expressions equivalent?

They aren't. A more appropriate question would be to list all of the errors
in the code.

>/* INCLUDE FILES */
># include "stdio.h"
># include "stdlib.h"
># include "conio.h"
>
>/* DATA DECLARATIONS */
>int a[3][5];
>int i=1;
>int j=1;
>
>main()
> {
> /* MAIN MODULE */
> clrscr();
>
> a[1][1]=25; // INITIALIZE
>

> printf("\n 1=%d ",*(a[i]+j));

> printf("\n 2=%d ",(*(a+i))[j]);

> printf("\n 3=%d ",*((*(a+i))+j));


> printf("\n 4=%d ",*(&a[0][0]+5*i+j));

> printf("\n 5=%d ",a[i][j];

> return(0);
> }

If you're going to set a test on C it is a good idea to use C code. Neither
conio.h or clrscr() are defined by the C language and // is a syntax error.
The last printf line is missing a )

The correct way to include standard header files is, for example,

#include <stdio.h>

Using "" instead of <> will probably work but may include a user file of that
name instead of the standard system header. There doesn't appear to be any
reason to include stdlib.h in the code.

&a[0][0]+5*i+j results in undefined behaviour since you are exceeding the
bounds of the array a[0].

The rest are trivially equivalent since the 'value' of an array in an
expression is a pointer to its first element and C defines a[b] to mean
exactly the same as (*((a)+(b))). Just apply this suitably to a[i][j] and
you can produce the other expressions.

--
-----------------------------------------
Lawrence Kirby | fr...@genesis.demon.co.uk
Wilts, England | 7073...@compuserve.com
-----------------------------------------

Tanmoy Bhattacharya

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
In article <40s2fi$3...@news.iag.net>, jat...@iag.net (John R Buchan (jatmon))
writes:
<snip>
|> >int a[3][5];
<snip>

|> &a[0][0] + 6 == &a[1][1] <6 ints from the beginning of the array>,

Not quite! The committee seems to have decided that anything beyond &a[0][0]
+ 5 leads to undefined behaviour (and even the +5 cannot be dereferenced),
even though we know that the address &a[0][0]+6 is intuitively valid and
`should' refer to &a[1][1].

This is probably to help bounds checking compilers to be able to do their
job. The decision states, roughly, that when the standard talks about a
pointer staying within an array object, it is talking about the smallest
relevant object. Here, any pointer `based' on &a[0][0], must stay inside (or
barely outside: the one off the end rule) the array object a[0]. A pointer
based on &a[0] must stay within (or one off the end of) the array a.

So what about (int*)&a[0] + 6? Is this allowed. I guess so, except nowhere in
the standard does it say that (int*)&a[0] is the same as &a[0][0]! (It does
however imply that (int(*)[])(int*)&a[0] is the same as &a[0], but that is
not quite the same thing. The statement about casting a struct/union member
pointer to/from the struct union pointer should probably be enlarged to array
element-array pointer conversions as well: but, the standard does not do it
yet, I guess.)

(I do assume (int*)&a[0] == &a[0][0] when I really need to.)

My explanation of pointers `based' on other pointers reminds me of noalias.
And they thought _that_ was complicated :-)

Cheers
Tanmoy
--
tan...@qcd.lanl.gov(128.165.23.46) DECNET: BETA::"tan...@lanl.gov"(1.218=1242)
Tanmoy Bhattacharya O:T-8(MS B285)LANL,NM87544-0285,USA H:#3,802,9 St,NM87545
Others see <gopher://yaleinfo.yale.edu:7700/00/Internet-People/internet-mail>,
<http://alpha.acast.nova.edu/cgi-bin/inmgq.pl>or<ftp://csd4.csd.uwm.edu/pub/
internetwork-mail-guide>. -- <http://nqcd.lanl.gov/people/tanmoy/tanmoy.html>
fax: 1 (505) 665 3003 voice: 1 (505) 665 4733 [ Home: 1 (505) 662 5596 ]

Robert Fry

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
>In article <40rrl8$q...@news.computek.net>, bom...@computek.net says...
>>
>>I had this problem on a test in C recently, needless to say no one
>>got it right.
>>
>>Why are each of the printed expressions equivalent?
>>
>>/* INCLUDE FILES */
>># include "stdio.h"
>># include "stdlib.h"
>># include "conio.h"
>>
>>/* DATA DECLARATIONS */
>>int a[3][5];
>>int i=1;
>>int j=1;
>>
>>main()
>> {
>> /* MAIN MODULE */
>> clrscr();
>>
>> a[1][1]=25; // INITIALIZE
>>
>> printf("\n 1=%d ",*(a[i]+j));
>> printf("\n 2=%d ",(*(a+i))[j]);
>> printf("\n 3=%d ",*((*(a+i))+j));
>> printf("\n 4=%d ",*(&a[0][0]+5*i+j));

I'll note that this one is not necessarily portable, assuming as it does
something about the layout of an array that I don't /think/ the compiler
is required to honor.

>> printf("\n 5=%d ",a[i][j];

And note that this one has a typo, and won't compile ...

>> return(0);
>> }
>>


John R Buchan (jatmon)

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
In article <40t03g$7...@newshost.lanl.gov>, tan...@qcd.lanl.gov says...

What you appear to be saying is basically that the standard does not guarantee
that all of the elements of a multidimensional array will be contiguous in
memory. ?? Is this correct? I thought that one of the properties of arrays
was that their elements were contiguous. Since a is an array of type array
of type in int (size 5), it would seem that all if the elements must be
contiguous. Can the compiler legally store a as an array of 3 pointers to
arrays of 5 ints (or some other such non-contiguous scheme)?

Or did I entirely misunderstand your post?

I'm not trying to contradict you. I just want to get this clear. Thanks.

Tanmoy Bhattacharya

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
In article <40tam8$j...@news.iag.net>, jat...@iag.net (John R Buchan (jatmon))

writes:
<snip>
|> >|> >int a[3][5];
|> ><snip>
|> >|> &a[0][0] + 6 == &a[1][1] <6 ints from the beginning of the array>,
|> >
|> >Not quite! The committee seems to have decided that anything beyond
&a[0][0]
|> >+ 5 leads to undefined behaviour (and even the +5 cannot be dereferenced),
|> >even though we know that the address &a[0][0]+6 is intuitively valid and
|> >`should' refer to &a[1][1].
|> >
|> >This is probably to help bounds checking compilers to be able to do their
|> >job. The decision states, roughly, that when the standard talks about a
|> >pointer staying within an array object, it is talking about the smallest
|> >relevant object. Here, any pointer `based' on &a[0][0], must stay inside
(or
|> >barely outside: the one off the end rule) the array object a[0]. A pointer
|> >based on &a[0] must stay within (or one off the end of) the array a.
<snip>

|> What you appear to be saying is basically that the standard does not
guarantee
|> that all of the elements of a multidimensional array will be contiguous in
|> memory. ?? Is this correct? I thought that one of the properties of
arrays
|> was that their elements were contiguous. Since a is an array of type array
|> of type in int (size 5), it would seem that all if the elements must be
|> contiguous. Can the compiler legally store a as an array of 3 pointers to
|> arrays of 5 ints (or some other such non-contiguous scheme)?

The standard does guarantee that the elements are contiguous. What it does
not guarantee is that the addition is valid! Yes, this is peculiar, not many
of us like it; but that is what the committee says. It is guaranteed that
(&a[0][0] + 5) == &a[1][0], however, (&a[0][0] + 5) + 1 is undefined whereas
&a[1][0] + 1 is perfectly well defined!

To repeat, the _addition_ of the integer 6 to the pointer &a[0][0] is invalid
in the case under consideration; even though there does exist an integer
6*sizeof(int) bytes away from this address.

|> Or did I entirely misunderstand your post?

It is difficult to understand: I don't understand it myself :-) &a[1][0] -
&a[0][0] is similarly undefined, though

(&a[1] - &a[0])*sizeof(a[0])/sizeof(a[0][0])

is perfectly okay!

John R Buchan (jatmon)

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
In article <40tam8$j...@news.iag.net>, jat...@iag.net says...

>
>In article <40t03g$7...@newshost.lanl.gov>, tan...@qcd.lanl.gov says...
>>
>>In article <40s2fi$3...@news.iag.net>, jat...@iag.net (John R Buchan (jatmon))

>>writes:
>><snip>
>>|> >int a[3][5];
>><snip>
>>|> &a[0][0] + 6 == &a[1][1] <6 ints from the beginning of the array>,
>>
>>Not quite! The committee seems to have decided that anything beyond &a[0][0]
>>+ 5 leads to undefined behaviour (and even the +5 cannot be dereferenced),
>>even though we know that the address &a[0][0]+6 is intuitively valid and
>>`should' refer to &a[1][1].
>>
>>This is probably to help bounds checking compilers to be able to do their
>>job. The decision states, roughly, that when the standard talks about a
>>pointer staying within an array object, it is talking about the smallest
>>relevant object. Here, any pointer `based' on &a[0][0], must stay inside (or
>>barely outside: the one off the end rule) the array object a[0]. A pointer
>>based on &a[0] must stay within (or one off the end of) the array a.
>>
>>So what about (int*)&a[0] + 6? Is this allowed. I guess so, except nowhere in
>>the standard does it say that (int*)&a[0] is the same as &a[0][0]! (It does
>>however imply that (int(*)[])(int*)&a[0] is the same as &a[0], but that is
>>not quite the same thing. The statement about casting a struct/union member
>>pointer to/from the struct union pointer should probably be enlarged to array
>>element-array pointer conversions as well: but, the standard does not do it
>>yet, I guess.)
>>
>>(I do assume (int*)&a[0] == &a[0][0] when I really need to.)
>>
>>My explanation of pointers `based' on other pointers reminds me of noalias.
>>And they thought _that_ was complicated :-)
>>
>
>What you appear to be saying is basically that the standard does not guarantee
>that all of the elements of a multidimensional array will be contiguous in
>memory. ?? Is this correct? I thought that one of the properties of arrays
>was that their elements were contiguous. Since a is an array of type array
>of type in int (size 5), it would seem that all if the elements must be
>contiguous. Can the compiler legally store a as an array of 3 pointers to
>arrays of 5 ints (or some other such non-contiguous scheme)?
>
>Or did I entirely misunderstand your post?
>
>I'm not trying to contradict you. I just want to get this clear. Thanks.
>

I may have just come up with an answer. Is this a viable explination
for the restriction you mentioned? (still assuming that array elements
are required to be contiguous in memory)

Given:

int ary[3][5];
int *ptr = &ary[0][0];

ary[0] is an array of 5 ints (which will be contiguous)
ary is an array of 3 arry_of_5_ints (which will be contiguous)

This seems to indicate that all 15 ints will be contiguous in memory.
However, what if the compiler added a 1 char pad to the end of the type
array_of_5_ints to meet some alignment requirement?

The rules about elements being contiguous would still be met for each
of the types (arrar_of_5_ints and array_of_array_of_5_ints), but there
would now be a char(byte) separating each group of 5 ints in memory.
So you couldn't use ptr to step through all 15 ints, because at ptr[5]
you would have encountered one of the pads and would no longer be
aligned on the ints.

(size and endianness not relevant. This should work for any type)
H = high order byte
L = low order byte
P = pad byte


ary[0] ary[1] ary[2]
____________________ ____________________ ____________________
| | | | | | | | | | | | | | | | | |
/ \ / \ / \ / \ / \ | / \ / \ / \ / \ / \ | / \ / \ / \ / \ / \ |
L H L H L H L H L H P L H L H L H L H L H P L H L H L H L H L H P
\ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ /
| | | | | | | | | | | | | | |
ptr + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
/|\
misalignment starts here _|


(I realize that this subject is a bit off topic for this group and
I appologize for it. Hopefully it won't continue for long.)

Steve Summit

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
(John Baum) writes:
> I had this problem on a test in C recently, needless to say no one
> got it right.

In some ways, it's a nice problem. I hope it was really on a
test you had in the past, and not on a homework assignment that
isn't due yet.

> Why are each of the printed expressions equivalent?
>

> int a[3][5];
> int i=1;
> int j=1;
>

> a[1][1]=25; // INITIALIZE
>
> printf("\n 1=%d ",*(a[i]+j));
> printf("\n 2=%d ",(*(a+i))[j]);
> printf("\n 3=%d ",*((*(a+i))+j));
> printf("\n 4=%d ",*(&a[0][0]+5*i+j));

> printf("\n 5=%d ",a[i][j];

(As an aside, does anyone know why so much code written for The
Operating System We Do Not Name uses \n *before* each line,
instead of the more usual after?)

The problem relates to the fundamental relationship between
arrays and pointers in C. First of all, if a pointer p points to
a cell i of an array:

p = &a[i]

then the expression p + j yields a pointer to the cell j elements
past cell i. (In other words, p + j is &a[i+j], and *(p+j) is a[i+j].)
For reference later, call this Rule 1.

Secondly, the value of an array when it appears in an expression
is (which a few exceptions which are irrelevant to the current
discussion), by definition, a pointer to the array's first element.
In other words, the assignment

p = a

is equivalent to

p = &a[0]

Call this Rule 2.

From these two facts, we can derive this important identity:
the expression

a[i]

is exactly the same as

*((a) + (i))

If you'd like a more detailed proof, let

p = a

or, equivalently (by Rule 2),

p = &a[0]

Then

p + i

is

&a[0+i] (by Rule 1)

or just

&a[i]

and

*(p+i)

is

a[0+i]

or

a[i]

The identity is usually stated as a[i] == *((a) + (i)), with
extra pairs of parentheses, since a and i may in fact be
arbitrary expressions, not necessarily simple variables.
Call this identity Rule 3.

With these rules in hand, we may analyze the five expressions
in the stated problem. Number 5 is the most straightforward:
a[i][j] is a traditional "two-dimensional" array subscript.
Why are the other four equivalent? For clarity in the following
derivations, let us restate Rule 3 as e1[e2] == *((e1)+(e2)).

1. *(a[i]+j) is a[i][j], by a single, simple application of
Rule 3, where e1 = a[i] and e2 = j.

2. (*(a+i))[j] is (a[i])[j] which is a[i][j], again by a single
application of Rule 3 where e1 = a and e2 = i.

3. *((*(a+i))+j) is *(a[i]+j) by a single application with e1 = a
and e2 = i (as for case 2), which is further equivalent to
a[i][j], by case 1.

4. *(&a[0][0]+5*i+j) is a bit of a mess, and simple applications
of the rules we've been using so far won't be entirely
sufficient to explicate it, for the very good reason that this
case does not itself quite follow the rules of C. (It is for
this reason that I characterized this as "In some ways... a
nice problem" and not "a nice problem.")

First we'll do it step by step, by applying the rules blindly
and on faith, even though we may not thereby derive any
intuitive understanding of what's going on. We will also need
to remind ourselves of Rule 2 above, namely that if an array
e3 (we'd been calling it a) appears in an expression, it's
equivalent to &e3[0].

*(&a[0][0]+5*i+j)
= *(a[0]+5*i+j) by Rule 2 with e3 = a[0]
= a[0][5*i+j] by Rule 3 with e1 = a[0], e2 = 5*i+j

Now we have to start waving our hands a bit. a[0][5*i+j] is
the 5*i+jth cell of the array a[0]. But a[0] (like all three
arrays in a) is an array of 5 elements, so if i > 0, we'll
have gone off its end. Since the next thing after a[0] in
memory is a[1] (all of a's elements are supposed to be
contiguous), we can convince ourselves that a[0][5*i+j] ought
to be a[1][5*(i-1)+j], or, by extension, that it's also
a[i][j]. But this is, I'll admit, not a wholly satisfying
explanation, because we haven't been rigorous in our
application of the three rules above.

Here's an alternate explanation which may be slightly more
satisfying, although it's even less rigorous. Imagine that we
have our array

int a[3][5];

and that we have a second array,

int a2[15];

on top of it somehow. (One way to overlay two arrays like
this would be with a union: union {int a[3][5]; int a2[15];}; .)
Thinking about this second, parallel, overlapping array, we
can see that

&a[0][0] =?= &a2[0]

and that

a[0][j] =?= a2[j] for 0 <= j < 5

(where the notation =?= means "handwaving equivalence"). By
extension, we can also see, (he claims), that

a[i][j] =?= a2[5*i + j]

which gives us another handle on part 4 of the original
problem:

*(&a[0][0]+5*i+j)
= *(&a2[0]+5*i+j) by overlap of a and a2
= *(a2+5*i+j) by Rule 2 with e3 = a2
= a2[5*i+j] by Rule 3 with e1 = a2, e2 = 5*i+j
= a[i][j] by overlap of a and a2

* * *

So we see that part 4 of the original problem can be quite tricky
to answer. I know quite a bit about C, and I can't come up with
a satisfactory explanation for it. (If I knew less about C, I
might be able to come up with a satisfying explanation, and it
might be the sort of explanation that the instructor assigning
the problem was looking for.)

But part 4 isn't really important to be able to answer. If you
can explain it, it indicates that you understand how arrays are
laid out in memory, but it does not indicate anything particular
about your knowledge of how arrays are defined and properly used.
(In fact, if you can explain it, your ability to do so may
indicate a deficiency in your knowledge, because if you knew
enough, you wouldn't be able to :-) .)

Explaining how parts 1, 2, 3, and 5 are equivalent is a useful
exercise, because it indicates understanding of an important
identity in C. But don't worry if part 4 doesn't make perfect
sense, because it doesn't.

Steve Summit
s...@eskimo.com

Tanmoy Bhattacharya

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
In article <40tdvp$j...@news.iag.net>, jat...@iag.net (John R Buchan (jatmon)) writes:
<snip>
|> I may have just come up with an answer. Is this a viable explination
|> for the restriction you mentioned? (still assuming that array elements
|> are required to be contiguous in memory)
|>
|> Given:
|>
|> int ary[3][5];
|> int *ptr = &ary[0][0];
|>
|> ary[0] is an array of 5 ints (which will be contiguous)
|> ary is an array of 3 arry_of_5_ints (which will be contiguous)
|>
|> This seems to indicate that all 15 ints will be contiguous in memory.
|> However, what if the compiler added a 1 char pad to the end of the type
|> array_of_5_ints to meet some alignment requirement?
|>
|> The rules about elements being contiguous would still be met for each
|> of the types (arrar_of_5_ints and array_of_array_of_5_ints), but there
|> would now be a char(byte) separating each group of 5 ints in memory.
|> So you couldn't use ptr to step through all 15 ints, because at ptr[5]
|> you would have encountered one of the pads and would no longer be
|> aligned on the ints.

No, this explanation is incorrect: because arrays are _not_ allowed to be
padded.

However, let us try another way of explaining what I was trying to say:

Let us start with the simple case, so that the parallel is clear:

ary is an array of 3 array_of_5_ints.

ary[0] is the first ary_of_5_ints of this array, arr[1] is the second
ary_of_5_ints, ary[2] is the third ary_of_5_ints, ary[3] is invalid, but
ary+3 is valid (you are allowed to go one past the end of the array, but you
are not allowed to dereference it), and ary+4 is disallowed (You are not even
allowed to add 4 to ary).

Now concentrate on ary[0]. This is an array of 5 ints. So, applying rules
similar to the above, ary[0][0], ary[0][1], ary[0][2], ary[0][3] and
ary[0][4] are all valid. ary[0]+5 is also valid (one past the last rule
explained above), but ary[0][5] is disallowed, whereas ary[0]+6 itself
is disallowed!

If you see the similarity in the above two paras, you will get to the logic
the committee is trying to follow. (Only a compiler which explicitly checks
for the violation of this rule has any hope of detecting this: but people do
like bounds checking compilers ... so such compilers may exist.)

Of course, note that ary[0]+5 is _equal to_ &ary[1][0] (because no padding is
allowed in arrays). On the other hand it is equally true *(ary[0]+5) is
undefined whereas *&ary[1][0] is, of course, defined. This is perhaps the
only place in C, where two equal rvalues of the same type behave differently.
This is a crazy set of affairs, but a rule worth remembering. _Never_ refer
to ary[1][0] as ary[0][5].

A similar situation obtained in other languages, e.g. Fortran 77 or Pascal as
well (I do not know much about the Fortran 90 _standard_). However, there, it
causes no problem: it did not have pointers, and did not try to define
subscripting of arrays in terms of addition and dereferencing of pointers. It
seems to me that the rule that is being employed here is one possible
interpretation of the standard as written; and this interpretation was chosen
over others in false analogy with dissimilar languages.

Be that as it may, this is how the language is defined. Till this
interpretation is changed, if ever, or till some one can demonstrate that we
misunderstood the interpretation of the committee, we ought to follow it.

John R Buchan (jatmon)

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
In article <40tgm0$e...@newshost.lanl.gov>, tan...@qcd.lanl.gov says...
>
<snip>

>
>No, this explanation is incorrect: because arrays are _not_ allowed to be
>padded.

<Good. I'd kind of wondered about that concept.>

I should have waited for your first reply, before posting my second.
I was just trying to come up with a reason why *(&a[0][0] + 6) might
fail to return the value of a[1][1] (even though I'd be unlikely
to ever write code like this). I've never been good at accepting
"because it says so" as an answer. I prefer to understand the reason
behind the rule. Thanks for the clarification.

I now understand this from the concept of bounds checking, but that
raises another question. I was under the impression that c provided
no bounds checking facilities (I understand that compilers can do so,
if they wish). So, Why does this rule exist just to make it easier
for the compiler that does implement a feature that the language
itself doesn't support? This seems a little odd.

Or is it more that the language supports bounds checking, but does
not actually enforce it? It leaves that option open to the compilers.

Tanmoy Bhattacharya

unread,
Aug 16, 1995, 3:00:00 AM8/16/95
to
In article <40tkui$q...@news.iag.net>, jat...@iag.net (John R Buchan (jatmon))
writes:
<snip>

|> Or is it more that the language supports bounds checking, but does
|> not actually enforce it? It leaves that option open to the compilers.
|>

It seems so, yes.

Dan Pop

unread,
Aug 17, 1995, 3:00:00 AM8/17/95
to
In <DDF2B...@eskimo.com> s...@eskimo.com (Steve Summit) writes:

>In article <40rrl8$q...@news.computek.net>, bom...@computek.net
>(John Baum) writes:
>>

>> printf("\n 5=%d ",a[i][j]);


>
>(As an aside, does anyone know why so much code written for The
>Operating System We Do Not Name uses \n *before* each line,
>instead of the more usual after?)

Probably because TOSWDNN automatically writes a newline to the console
before printing a new prompt. So, if you don't want an empty line after
your last line of output, you have to avoid the newline at the end.
But since the statement which outputs the last line in a program might
change during program's lifetime, it's more convenient to have the
newline at the beginning of the line.

Anyway, this is only my theory.

Dan
--
Dan Pop
CERN, CN Division
Email: Dan...@mail.cern.ch
Mail: CERN - PPE, Bat. 31 R-004, CH-1211 Geneve 23, Switzerland

Andy J Robb

unread,
Aug 17, 1995, 3:00:00 AM8/17/95
to
bom...@computek.net (John Baum) wrote:


>I had this problem on a test in C recently, needless to say no one
>got it right.

>Why are each of the printed expressions equivalent?


>/* INCLUDE FILES */
># include "stdio.h"
># include "stdlib.h"
># include "conio.h"

>/* DATA DECLARATIONS */
>int a[3][5];

a is declared as three rows of five ints
>int i=1;
>int j=1;
set the indices to the second row and column


>main()
> {
> /* MAIN MODULE */
> clrscr();
>

> a[1][1]=25; // INITIALIZE
>
> printf("\n 1=%d ",*(a[i]+j));

a[i] is a pointer to the second row
j is the offset in that row


> printf("\n 2=%d ",(*(a+i))[j]);

a+i is an int** pointing to the second row
(*(a+i)) IS a[i]
> printf("\n 3=%d ",*((*(a+i))+j));
this is the previous two combined


> printf("\n 4=%d ",*(&a[0][0]+5*i+j));

&a[0][0] is a[0]
The 5 comes from sizeof a / sizeof a[0]
and is the length of each row
> printf("\n 5=%d ",a[i][j];
OK so you forgot the closing parenthesis (I forgive you)
I;ve got to go now!

Regards,
Andy Robb.

> return(0);
> }

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.2i

mQCNAy/MpRwAAAEEAOt6uBYqT8yv9EmqNhK8m6v+bYi8QjnGW3Bo6iU1gsMj5pa6
MHgq99c8deADbE3cbJ6uZS9v5pZE3WCf6HCQjlB5iULA5RZzMdAumd/WUzuL9UT3
B44D9EqqFIL79FlYb56v4oKFqFp1/J2bIpYUwnUvabGzGjdLrpPl4P16x9sNAAUR
tCNBbmR5IEogUm9iYiA8QUpSb2JiQHBhdmlsaW9uLmNvLnVrPrQhQW5keSBSb2Ji
IDxBSlJvYmJAcGF2aWxpb24uY28udWs+
=/wVD
-----END PGP PUBLIC KEY BLOCK-----


0 new messages