Re: contiguity of arrays

From: Michael Mair (mairRemove_for_mailinG_at_ians.uni-stuttgart.de)
Date: 09/28/04


Date: Tue, 28 Sep 2004 16:50:32 +0200

Hi pete,

>>>If it was
>>> int a[2][2] = {{1, 2}, {3, 4}}, *b = (int *)a;
>>> ^^^^^^^
>>>instead,
>>>there wouldn't be a problem accessing b[3], would there?
>>
>>There would. The same arguments hold.
>
>
> No, the same arguments don't hold.

I am sorry but I am not sure I understand you.

As a is an array of arrays of two ints and not a int **,
we effectively have a being a starting address and not
an address of a starting address. In other words: a does not
decay into an (int **).
This does not change by your applying the typecast.

Please explain your reasoning so we can work with it.

> Is this legal? Must it print 4?
>
> int a[2][2] = {{1, 2}, {3, 4}}, *b = a[0];
> printf("%d\n", *(b + 3));

Of course not. You still point b to the address of a[0][0],
thus b+3 would point to the address of "a[0][3]". As arrays
are stored contiguously, you could access a[0][3] if a was
declared a[2][X], where X>=4.
But as it is, you try to access an address outside of the
object (int *)a[0] is pointing to. The difference between
a[1] and a[0] might not be (ptrdiff_t) 2*sizeof(int).
Imagine a system with sizeof(int)*CHAR_BIT==32 and optimal
access speed at 96-Bit aligned addresses where the compiler
thinks it fun to 96-Bit align every array "row", giving you
here a "padding" int but being able to get a[X][0] and a[X][1],
X in the appropriate range for a, very quickly to wherever they
are needed.

> The problem originally was that b had the address of the first
> element of a[0]. a[0] has two elements, a[0][0] and a[0][1].
> The address of b[3] is outside of a[0][1],
> which is to say that b[3] is beyond the boundary of a[0].
>
> For
> b = (int *)a;
> b has the address of the first element of a, converted to int *.
> a has two elements, a[0] and a[1].
> The address of b[3] is not outside of a[1],
> which is to say that b[3] is not beyond the boundary of a.

Umh, once again: a does not decay into an (int **).
What you want is really
   int (*b)[2];
   b = a;
Then b == a[0] and b+1 == a[1].

So ka?

--Michael



Relevant Pages

  • (patch for Bash) regex case statement
    ... Following up on my previous patch for regex conditional tests, ... /* Return an array of strings; ... int dollarflag, zeropad, compareflag; ... SHELL_VAR *var; ...
    (comp.unix.shell)
  • Re: Strategy or Iterator?
    ... It would be possible to write a class that returns the variations ... GNU General Public License for more details. ... protected CombinatoricOperator(Telements, int r) { ... An integer array backing up the original one to keep track of the ...
    (comp.lang.java.programmer)
  • (patch for Bash) regex conditional tests
    ... 'regex' are returned in array variable SUBMATCH. ... Skipping of positional parameters, array elements, string ... int dollarflag, zeropad, compareflag; ... SHELL_VAR *var; ...
    (comp.unix.shell)
  • Re: Warning on assigning a function-returning-a-pointer-to-arrays
    ... This declares pfunc as a function taking no arguments and returning ... int x, y; ... Presumably pfuncwill return a pointer to a single int, ... or the first of a sequence of "array 5 of int"s. ...
    (comp.lang.c)
  • Re: Memory Allocation Problem, please help
    ... typedef struct word_tag{ ... array is not an array. ... static int total_word_count; ... static int word_index(const char *word); ...
    (comp.lang.c)