Can I tab[-1] ?

Discussion in 'C Programming' started by fir, Dec 20, 2012.

  1. fir

    fir Guest

    Can I use c arrays in such way tab[-1] or tab[-1][-1] (I mean when index is below zero)?

    Also - I think if try to use some way of optimization
    where instead of checking some edge values like

    if(x>=0 && x<500 && y>=0 && y<500)
    tab[y][x] = 1;

    alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1

    but here it would be convenient to cast some pointer ot type tab[500][500] 'into' wider_tab[502][502]
    in such way that tab[0][0] wolul correspond to wider_tab[1][1] (and tab[-1][-1] to wider_tab[0][0])

    Can I get something like that? (If not I am sad)
     
    fir, Dec 20, 2012
    #1
    1. Advertising

  2. fir <> wrote:
    > Can I use c arrays in such way tab[-1] or tab[-1][-1]
    > (I mean when index is below zero)?


    > Also - I think if try to use some way of optimization
    > where instead of checking some edge values like


    > if(x>=0 && x<500 && y>=0 && y<500)
    > tab[y][x] = 1;


    > alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1


    Not with actual arrays, but you can with pointers and arrays
    of pointers.

    > but here it would be convenient to cast some pointer ot type
    > tab[500][500] 'into' wider_tab[502][502] in such way that
    > tab[0][0] wolul correspond to wider_tab[1][1]
    > (and tab[-1][-1] to wider_tab[0][0])


    > Can I get something like that? (If not I am sad)


    There is much discussion about pointers outside the allocated
    space, such that the offset is inside. In this case, though,
    the pointer is inside the allocated space, such that adding -1
    is still inside.

    -- glen
     
    glen herrmannsfeldt, Dec 20, 2012
    #2
    1. Advertising

  3. fir

    fir Guest

    W dniu czwartek, 20 grudnia 2012 08:43:49 UTC+1 użytkownik glen herrmannsfeldt napisał:
    > fir <> wrote:
    > > Can I use c arrays in such way tab[-1] or tab[-1][-1]
    > > (I mean when index is below zero)?

    >
    > > Also - I think if try to use some way of optimization
    > > where instead of checking some edge values like

    >
    > > if(x>=0 && x<500 && y>=0 && y<500)
    > > tab[y][x] = 1;

    >
    >
    >
    > > alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1

    > Not with actual arrays, but you can with pointers and arrays
    > of pointers.
    >
    >
    >
    > > but here it would be convenient to cast some pointer ot type
    > > tab[500][500] 'into' wider_tab[502][502] in such way that
    > > tab[0][0] wolul correspond to wider_tab[1][1]

    >
    > > (and tab[-1][-1] to wider_tab[0][0])

    >
    >
    >
    > > Can I get something like that? (If not I am sad)

    >
    >
    >
    > There is much discussion about pointers outside the allocated
    > space, such that the offset is inside. In this case, though,
    > the pointer is inside the allocated space, such that adding -1
    > is still inside.
    >
    >


    you sure i cant do it with some static array[][] cast? I want such syntax tab[][] and also
    i need natural coordinates 0-500 for centre plus -1 and 501 for additional border, also I wnt efficiency - adequate simple casting would be the best, though i do anderstand that i should cast on something like tab[502][502]
    with somme offset (not tab[500][500]) and then
    used it in tab[-1 to 501 included] so I just need recast tab[502][502] a 503 fields further

    as to array of pointers with same syntax of usage t[j] - is it more efficient or less
    (it is very important question and i still not sure)
     
    fir, Dec 20, 2012
    #3
  4. fir

    Philip Lantz Guest

    fir wrote:
    > Also - I think if try to use some way of optimization
    > where instead of checking some edge values like
    >
    > if(x>=0 && x<500 && y>=0 && y<500)
    > tab[y][x] = 1;
    >
    > alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1
    >
    > but here it would be convenient to cast some pointer to type
    > tab[500][500] 'into' wider_tab[502][502] in such way that
    > tab[0][0] would correspond to wider_tab[1][1] (and tab[-1][-1]
    > to wider_tab[0][0])


    int wider_tab[501*501+1];
    int (*tab)[500] = (int (*)[500])&wider_tab[500+1];

    tab[0][0] is wider_tab[501]
    tab[1][0] is wider_tab[1001]
    tab[500][500] is wider_tab[501*501]
    tab[-1][-1] is wider_tab[0]

    There is a caveat: It's possible that the standard allows (int [500]) to
    have a stricter alignment requirement than (int [502*502]), which would
    mean that the cast isn't guaranteed to behave. I'm not convinced that
    it's allowed, and even if it is, I am confident that no implementation
    actually has such a requirement.

    It's also possible that an implementation for x86 in huge model (where
    arrays can span multiple segments), or similar architectures, could have
    trouble with this, if the compiler was doing some very sophisticated
    optimizations based on knowledge of how the array boundaries line up
    with with segment boundaries. The normal brute force approach to huge
    model shouldn't have any problem with it, though.
     
    Philip Lantz, Dec 20, 2012
    #4
  5. fir <> wrote:
    >> fir <> wrote:
    >> > Can I use c arrays in such way tab[-1] or tab[-1][-1]
    >> > (I mean when index is below zero)?


    (snip)

    >> > alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1


    (snip, then I wrote)
    >> Not with actual arrays, but you can with pointers and arrays
    >> of pointers.


    >> > but here it would be convenient to cast some pointer ot type
    >> > tab[500][500] 'into' wider_tab[502][502] in such way that
    >> > tab[0][0] wolul correspond to wider_tab[1][1]


    >> > (and tab[-1][-1] to wider_tab[0][0])


    (snip)

    > you sure i cant do it with some static array[][] cast?
    > I want such syntax tab[][] and also i need natural coordinates
    > 0-500 for centre plus -1 and 501 for additional border,
    > also I wnt efficiency - adequate simple casting would be the best,
    > though i do anderstand that i should cast on something
    > like tab[502][502] with somme offset (not tab[500][500]) and then
    > used it in tab[-1 to 501 included] so I just need recast
    > tab[502][502] a 503 fields further


    In the 1D case, you set a pointer to element 1, then all will
    be off by one.

    int tab1[503];
    int *tab=tab+1;

    Now tab[-1] through tab[501] exist. In most cases, the speed should
    be the same.

    > as to array of pointers with same syntax of usage
    > t[j] - is it more efficient or less
    > (it is very important question and i still not sure)


    In the 2D case, you have an array of pointers to arrays, which
    you can either generate pointers to existing arrays, or dynamically
    allocate them:

    int **tab2;
    tab2=malloc(503*sizeof(*tab2))+1;
    for(i=-1;i<502;i++) tab2=malloc(503*sizeof(**tab2))+1;

    Often it is done this way to allow for dynamic allocation, and
    not for efficiency reasons. It is a little hard to say which is
    more efficient, as it depends much on the processor, memory cache,
    and instruction overlap.

    (Note that -1 through 501 is 503 elements, not 502.)

    -- glen
     
    glen herrmannsfeldt, Dec 20, 2012
    #5
  6. Philip Lantz <> wrote:

    (snip)

    >> alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1


    >> but here it would be convenient to cast some pointer to type
    >> tab[500][500] 'into' wider_tab[502][502] in such way that
    >> tab[0][0] would correspond to wider_tab[1][1] (and tab[-1][-1]
    >> to wider_tab[0][0])


    (snip)

    > int wider_tab[501*501+1];
    > int (*tab)[500] = (int (*)[500])&wider_tab[500+1];


    > tab[0][0] is wider_tab[501]
    > tab[1][0] is wider_tab[1001]
    > tab[500][500] is wider_tab[501*501]
    > tab[-1][-1] is wider_tab[0]


    > There is a caveat: It's possible that the standard allows (int [500]) to
    > have a stricter alignment requirement than (int [502*502]), which would
    > mean that the cast isn't guaranteed to behave. I'm not convinced that
    > it's allowed, and even if it is, I am confident that no implementation
    > actually has such a requirement.


    Sometimes it is nice to have something aligned higher than the
    normal alignment, such as when using SSE modes that require 16 byte
    alignment. In most cases, though, it is up to the programmer to keep
    things aligned, not the compiler.

    > It's also possible that an implementation for x86 in huge model (where
    > arrays can span multiple segments), or similar architectures, could have
    > trouble with this, if the compiler was doing some very sophisticated
    > optimizations based on knowledge of how the array boundaries line up
    > with with segment boundaries.


    Yes, but in that case an array of large model pointers is a better choice.

    > The normal brute force approach to huge model shouldn't have any
    > problem with it, though.


    Besides, since the 80386 segments are up to 4GB, and pretty much no
    systems support even large model in 32 bit mode.

    (Yes, I did much work on the 80286 using arrays of far pointers.)

    -- glen
     
    glen herrmannsfeldt, Dec 20, 2012
    #6
  7. Robert Wessel <> wrote:

    (snip)

    > I'm less confident that using a -1 as an index is guaranteed to work,
    > but I think it might be.


    I believe it pretty much has to work. The other way around, subtracting
    from a pointer to allow the low end of an array to be 1 is not
    guaranteed to work, but was used in "Numerical Recipes in C" to make
    translation from Fortran to C easier.

    > I'm less convinced that it's a good idea, though...


    Hard to say.

    -- glen
     
    glen herrmannsfeldt, Dec 20, 2012
    #7
  8. fir

    Shao Miller Guest

    On 12/20/2012 03:28, Philip Lantz wrote:
    >
    > There is a caveat: It's possible that the standard allows (int [500]) to
    > have a stricter alignment requirement than (int [502*502]), which would
    > mean that the cast isn't guaranteed to behave. I'm not convinced that
    > it's allowed, and even if it is, I am confident that no implementation
    > actually has such a requirement.
    >


    Confidence: Agreed.

    C11's 6.2.8p4 seems to suggest that possible alignments are really
    derived from fundamental types.

    It'd seem odd if 'malloc(sizeof (int[502 * 502]))' had to worry about
    satisfying the possibility that you might be overallocating, but really
    interested in using the storage for an 'int[500]' with a stricter
    requirement than an 'int[502 * 502]'.

    - Shao Miller
     
    Shao Miller, Dec 20, 2012
    #8
  9. fir

    fir Guest

    W dniu czwartek, 20 grudnia 2012 10:16:48 UTC+1 użytkownik glen herrmannsfeldt napisał:
    > Robert Wessel <> wrote:
    >
    >
    > > I'm less convinced that it's a good idea, though...

    >
    >
    > Hard to say.
    >


    not to much hard to say ;-) it is good

    can be usefull as in my example of :

    x, y are random coordinates from x: -10 to 650, y: -10 to 500, there are large amounts of them only some are out of 0-640 0-480

    you dont want to if(x>=0 && x<640 && y>=0 && y<480) ... on thousands ofthem just need to alloc little more and if you can 'recast' it
    you can use natural coordinates (same as with pure method with if() checking/clipping,

    so imo it is welcome in c
     
    fir, Dec 20, 2012
    #9
  10. fir

    Shao Miller Guest

    On 12/20/2012 01:25, fir wrote:
    > Can I use c arrays in such way tab[-1] or tab[-1][-1] (I mean when index is below zero)?
    >


    I'd say it depends on the declaration. It is not clear from this
    question what the types of 'tab[-1]' or 'tab[-1][-1]' are expected to be.

    > Also - I think if try to use some way of optimization
    > where instead of checking some edge values like
    >
    > if(x>=0 && x<500 && y>=0 && y<500)
    > tab[y][x] = 1;
    >
    > alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1
    >


    I don't see any allocation. Could you share the bit of code that does
    the allocation?

    > but here it would be convenient to cast some pointer ot type tab[500][500] 'into' wider_tab[502][502]
    > in such way that tab[0][0] wolul correspond to wider_tab[1][1] (and tab[-1][-1] to wider_tab[0][0])
    >
    > Can I get something like that? (If not I am sad)
    >


    I'd say it depends on the declarations involved. It is not clear if you
    are working with an array of pointers or not, for example.

    You might or might not be interested in "Multi-Dimensional Array
    Simulator" at http://www.iso-9899.info/wiki/Code_snippets

    - Shao Miller
     
    Shao Miller, Dec 20, 2012
    #10
  11. fir

    Shao Miller Guest

    On 12/20/2012 03:34, Robert Wessel wrote:
    >
    > I think you can do something like this:
    >
    > int a[12][12];
    >
    > void f()
    > {
    > int (*b)[10][12]; // note: use only 0..9 in second index
    >
    > b = (int (*)[10][12])&(a[1][1]);
    >
    > (*b)[2][2] = 3;
    > }
    >
    > Given that the array layout is standardized, I *think* that doesn't
    > violate any rules. You'd have a row and column of "pad" around the
    > 10x10 array.
    >
    > I'm less confident that using a -1 as an index is guaranteed to work,
    > but I think it might be.
    >
    > I'm less convinced that it's a good idea, though...
    >


    (*b)[-1]
    *(*b - 1)

    In this context, '*b' has type 'int[10][12]' but yields an 'int(*)[12]'.
    Regardless of that, since 'b' points to an array, I believe that '*b -
    1' is out of bounds. I think the cast could discard "the actual" bounds
    and establish new ones; possibly interpreted by the implementation as an
    instruction to forget what it knew.

    - Shao Miller
     
    Shao Miller, Dec 20, 2012
    #11
  12. Philip Lantz <> writes:

    > fir wrote:
    >> Also - I think if try to use some way of optimization
    >> where instead of checking some edge values like
    >>
    >> if(x>=0 && x<500 && y>=0 && y<500)
    >> tab[y][x] = 1;
    >>
    >> alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1
    >>
    >> but here it would be convenient to cast some pointer to type
    >> tab[500][500] 'into' wider_tab[502][502] in such way that
    >> tab[0][0] would correspond to wider_tab[1][1] (and tab[-1][-1]
    >> to wider_tab[0][0])

    >
    > int wider_tab[501*501+1];
    > int (*tab)[500] = (int (*)[500])&wider_tab[500+1];
    >
    > tab[0][0] is wider_tab[501]
    > tab[1][0] is wider_tab[1001]
    > tab[500][500] is wider_tab[501*501]
    > tab[-1][-1] is wider_tab[0]


    I think the OP wants an 'dead' edge all the way round. I.e. I think
    they want:

    int wider_tab[(N+2)*(N+2)];
    int (*tab)[N+2] = (int (*)[N+2])&wider_tab[N+2+1];

    (for N=500). You could also (probably) get away with using plain 2D
    arrays for a little more clarity:

    int wider_tab[N+2][N+2];
    int (*tab)[N+2] = (void *)&wider_tab[1][1];

    For illustration, when N=5, the output of

    memset(wider_tab, -1, sizeof wider_tab); // ok, know...
    for (int i = 0; i < N; i++)
    for (int j = 0; j < N; j++)
    tab[j] = i*10 + j;
    for (int i = 0; i < N+2; i++, putchar('\n'))
    for (int j = 0; j < N+2; j++)
    printf("%3d", wider_tab[j]);

    would be:

    -1 -1 -1 -1 -1 -1 -1
    -1 0 1 2 3 4 -1
    -1 10 11 12 13 14 -1
    -1 20 21 22 23 24 -1
    -1 30 31 32 33 34 -1
    -1 40 41 42 43 44 -1
    -1 -1 -1 -1 -1 -1 -1

    <snip warnings>
    --
    Ben.
     
    Ben Bacarisse, Dec 20, 2012
    #12
  13. fir

    fir Guest

    W dniu czwartek, 20 grudnia 2012 14:38:45 UTC+1 użytkownik Ben Bacarisse napisał:
    > Philip Lantz <> writes:
    >
    >
    >
    > > fir wrote:

    >
    > >> Also - I think if try to use some way of optimization

    >
    > >> where instead of checking some edge values like

    >
    > >>

    >
    > >> if(x>=0 && x<500 && y>=0 && y<500)

    >
    > >> tab[y][x] = 1;

    >
    > >>

    >
    > >> alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1

    >
    > >>

    >
    > >> but here it would be convenient to cast some pointer to type

    >
    > >> tab[500][500] 'into' wider_tab[502][502] in such way that

    >
    > >> tab[0][0] would correspond to wider_tab[1][1] (and tab[-1][-1]

    >
    > >> to wider_tab[0][0])

    >
    > >

    >
    > > int wider_tab[501*501+1];

    >
    > > int (*tab)[500] = (int (*)[500])&wider_tab[500+1];

    >
    > >

    >
    > > tab[0][0] is wider_tab[501]

    >
    > > tab[1][0] is wider_tab[1001]

    >
    > > tab[500][500] is wider_tab[501*501]

    >
    > > tab[-1][-1] is wider_tab[0]

    >
    >
    >
    > I think the OP wants an 'dead' edge all the way round. I.e. I think
    >
    > they want:
    >
    >
    >
    > int wider_tab[(N+2)*(N+2)];
    >
    > int (*tab)[N+2] = (int (*)[N+2])&wider_tab[N+2+1];
    >
    >
    >
    > (for N=500). You could also (probably) get away with using plain 2D
    >
    > arrays for a little more clarity:
    >
    >
    >
    > int wider_tab[N+2][N+2];
    > int (*tab)[N+2] = (void *)&wider_tab[1][1];
    >


    that is exactly what i want, but here above is it vector of pointers or lite/solid block of addresable ram (with no other area pointers?),
    (somewhat sad to say but i forgot of was atways somewhat out to array pointer subtlities :/ like this)
    what way "int (*tab)[N+2]" should be read?


    >
    >
    > For illustration, when N=5, the output of
    >
    >
    >
    > memset(wider_tab, -1, sizeof wider_tab); // ok, know...
    >
    > for (int i = 0; i < N; i++)
    >
    > for (int j = 0; j < N; j++)
    >
    > tab[j] = i*10 + j;
    >
    > for (int i = 0; i < N+2; i++, putchar('\n'))
    >
    > for (int j = 0; j < N+2; j++)
    >
    > printf("%3d", wider_tab[j]);
    >
    >
    >
    > would be:
    >
    >
    >
    > -1 -1 -1 -1 -1 -1 -1
    >
    > -1 0 1 2 3 4 -1
    >
    > -1 10 11 12 13 14 -1
    >
    > -1 20 21 22 23 24 -1
    >
    > -1 30 31 32 33 34 -1
    >
    > -1 40 41 42 43 44 -1
    >
    > -1 -1 -1 -1 -1 -1 -1
    >
    >
    >
    > <snip warnings>
    >
    > --
    >
    > Ben.
     
    fir, Dec 20, 2012
    #13
  14. fir

    Tim Rentsch Guest

    fir <> writes:

    > Can I use c arrays in such way tab[-1] or tab[-1][-1] (I mean when index is below zero)?
    >
    > Also - I think if try to use some way of optimization
    > where instead of checking some edge values like
    >
    > if(x>=0 && x<500 && y>=0 && y<500)
    > tab[y][x] = 1;
    >
    > alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1
    >
    > but here it would be convenient to cast some pointer ot type tab[500][500] 'into' wider_tab[502][502]
    > in such way that tab[0][0] wolul correspond to wider_tab[1][1] (and tab[-1][-1] to wider_tab[0][0])
    >
    > Can I get something like that? (If not I am sad)


    The short answer is no. If E is any expression of array type,
    any use of (E)[-1] or even just ((E)-1) is undefined behavior.

    To get something like what you want, you would have to use
    an array of pointers, those pointers being of type (int *),
    and the type of 'tab' being (int **), with tab pointing at
    the second element of the array (ie, at index [1]). The
    pointers in the pointer array should point into a large
    one-dimensional array, eg, 'int tab_space[ 502 * 502 ];'.
     
    Tim Rentsch, Dec 20, 2012
    #14
  15. fir

    fir Guest

    W dniu czwartek, 20 grudnia 2012 18:12:44 UTC+1 użytkownik Tim Rentschnapisał:
    > fir <> writes:
    >
    >
    >
    > > Can I use c arrays in such way tab[-1] or tab[-1][-1] (I mean when index is below zero)?

    >
    > >

    >
    > > Also - I think if try to use some way of optimization

    >
    > > where instead of checking some edge values like

    >
    > >

    >
    > > if(x>=0 && x<500 && y>=0 && y<500)

    >
    > > tab[y][x] = 1;

    >
    > >

    >
    > > alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1

    >
    > >

    >
    > > but here it would be convenient to cast some pointer ot type tab[500][500] 'into' wider_tab[502][502]

    >
    > > in such way that tab[0][0] wolul correspond to wider_tab[1][1] (and tab[-1][-1] to wider_tab[0][0])

    >
    > >

    >
    > > Can I get something like that? (If not I am sad)

    >
    >
    >
    > The short answer is no. If E is any expression of array type,
    >
    > any use of (E)[-1] or even just ((E)-1) is undefined behavior.
    >
    >
    >
    > To get something like what you want, you would have to use
    >
    > an array of pointers, those pointers being of type (int *),
    >
    > and the type of 'tab' being (int **), with tab pointing at
    >
    > the second element of the array (ie, at index [1]). The
    >
    > pointers in the pointer array should point into a large
    >
    > one-dimensional array, eg, 'int tab_space[ 502 * 502 ];'.


    what with

    int (*tab)[N+2] = (void *)&wider_tab[1][1];

    isnt tab here a pointer to "int somechunk[502]" ?

    and if so, tab+1 (or tab[1]) woluld be next one "int some[502}" laying after previous -

    so if it is working -> (tab[j]) (or tab[j]), it should be working theway I would exactly like- so it would be grrt (great I mean)

    as to -1 as far as i remember ritche wrote
    (in c development historical note) that this
    square bracket syntax is only a sugar/alias
    to pointers *(a+5) becomes a[5] here (or even
    5[a] points the same as denoted in wiki - so it is maybe just mechanical trick), so
    by analogy if *(a-1) works a[-1] should be working also
     
    fir, Dec 20, 2012
    #15
  16. fir

    Shao Miller Guest

    On 12/20/2012 12:30, fir wrote:
    > W dniu czwartek, 20 grudnia 2012 18:12:44 UTC+1 użytkownik Tim Rentsch napisał:
    >> The short answer is no. If E is any expression of array type,
    >> any use of (E)[-1] or even just ((E)-1) is undefined behavior.
    >>

    >
    > as to -1 as far as i remember ritche wrote
    > (in c development historical note) that this
    > square bracket syntax is only a sugar/alias
    > to pointers *(a+5) becomes a[5] here (or even
    > 5[a] points the same as denoted in wiki - so it is maybe just mechanical trick), so
    > by analogy if *(a-1) works a[-1] should be working also
    >


    It is important to carefully note what Tim said about the type of 'E'.
    If 'E' is a _pointer_, that's different than if 'E' is an _array_ which
    happens to yield a pointer value in some contexts.

    If 'E' is an array, the pointer value it yields (when it's not the
    immediate operand of unary '&' or 'sizeof') is pointing to the lower
    bound for the array. Subtracting 1 from that pointer value is thus
    undefined behaviour, even if there so happens to be an object with
    suitable type (or any type) available immediately before the array.

    - Shao Miller
     
    Shao Miller, Dec 20, 2012
    #16
  17. fir

    Shao Miller Guest

    On 12/20/2012 13:17, Shao Miller wrote:
    > It is important to carefully note what Tim said about the type of 'E'.


    Apologies. I meant Mr. T. Rentsch.

    >
    > If 'E' is an array, the pointer value it yields (when it's not the
    > immediate operand of unary '&' or 'sizeof') [...]


    Apologies. I forgot C11's '_Alignof', too.

    - Shao Miller
     
    Shao Miller, Dec 20, 2012
    #17
  18. fir

    Philip Lantz Guest

    Robert Wessel wrote:
    > fir wrote:
    > >Can I use c arrays in such way tab[-1] or tab[-1][-1] (I mean when
    > >index is below zero)?
    > >
    > >Also - I think if try to use some way of optimization
    > >where instead of checking some edge values like
    > >
    > >if(x>=0 && x<500 && y>=0 && y<500)
    > > tab[y][x] = 1;
    > >
    > >alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1
    > >
    > >but here it would be convenient to cast some pointer to type
    > >tab[500][500] 'into' wider_tab[502][502] in such way that
    > >tab[0][0] would correspond to wider_tab[1][1] (and tab[-1][-1]
    > >to wider_tab[0][0])

    >
    >
    > I think you can do something like this:
    >
    > int a[12][12];
    >
    > void f()
    > {
    > int (*b)[10][12]; // note: use only 0..9 in second index
    >
    > b = (int (*)[10][12])&(a[1][1]);
    >
    > (*b)[2][2] = 3;
    > }
    >
    > Given that the array layout is standardized, I *think* that doesn't
    > violate any rules. You'd have a row and column of "pad" around the
    > 10x10 array.


    If you don't need to be able to use a negative index in the second
    dimension, you can do this without a cast, and the behavior is
    definitely guaranteed:

    int a[12][12];
    int (*b)[12] = &a[1];

    b[-1][0] is a[0][0]
    b[0][0] is a[1][0]


    > I'm less confident that using a -1 as an index is guaranteed to work,
    > but I think it might be.


    Using -1 as an index in a one-dimensional array is guaranteed to work:

    int a[12];
    int *b = &a[1];
    b[-1] /* This is guaranteed to access a[0]. */

    With a multi-dimensional array, it is less clear that the behavior is
    guaranteed when using -1 as an index for anything other than the last
    dimension, but I think it is, and even if it is not guaranteed by the
    standard, I believe it is guaranteed by all implementations.
     
    Philip Lantz, Dec 20, 2012
    #18
  19. fir

    Tim Rentsch Guest

    fir <> writes:

    > [citation for Tim Rentsch]
    >> fir <> writes:
    >>
    >>
    >>
    >> > Can I use c arrays in such way tab[-1] or tab[-1][-1] (I mean when index is below zero)?

    >>
    >> >

    >>
    >> > Also - I think if try to use some way of optimization

    >>
    >> > where instead of checking some edge values like

    >>
    >> >

    >>
    >> > if(x>=0 && x<500 && y>=0 && y<500)

    >>
    >> > tab[y][x] = 1;

    >>
    >> >

    >>
    >> > alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1

    >>
    >> >

    >>
    >> > but here it would be convenient to cast some pointer ot type tab[500][500] 'into' wider_tab[502][502]

    >>
    >> > in such way that tab[0][0] wolul correspond to wider_tab[1][1] (and tab[-1][-1] to wider_tab[0][0])

    >>
    >> >

    >>
    >> > Can I get something like that? (If not I am sad)

    >>
    >>
    >>
    >> The short answer is no. If E is any expression of array type,
    >>
    >> any use of (E)[-1] or even just ((E)-1) is undefined behavior.
    >>
    >>
    >>
    >> To get something like what you want, you would have to use
    >>
    >> an array of pointers, those pointers being of type (int *),
    >>
    >> and the type of 'tab' being (int **), with tab pointing at
    >>
    >> the second element of the array (ie, at index [1]). The
    >>
    >> pointers in the pointer array should point into a large
    >>
    >> one-dimensional array, eg, 'int tab_space[ 502 * 502 ];'.


    Dear Professor:

    Please change your settings, or edit your postings, or both, to
    get rid of extraneous blank lines.

    > what with
    >
    > int (*tab)[N+2] = (void *)&wider_tab[1][1];
    >
    > isnt tab here a pointer to "int somechunk[502]" ?
    >
    > and if so, tab+1 (or tab[1]) woluld be next one "int some[502}" laying
    > after previous -
    >
    > so if it is working -> (tab[j]) (or tab[j]), it should be
    > working the way I would exactly like- so it would be grrt (great I
    > mean)


    Indexing in C is not defined just in terms of address
    calculation. Address calculation is one aspect, but there
    are additional constraints, and those constraints must be
    observed; otherwise ALL BETS ARE OFF. The approach
    described above violates those constraints. ANY approach
    using pointer to array types, that attempts to index an
    expression of array type with an index value of -1, will
    violate the constraints. There is NO WAY to do what you
    want to do using regular arrays or pointers to arrays; use
    an array of pointers, and use type (int **) for the
    accessing identifer ('tab' in the above) instead.

    > as to -1 as far as i remember ritche wrote (in c development
    > historical note) that this square bracket syntax is only a
    > sugar/alias to pointers *(a+5) becomes a[5] here (or even 5[a]
    > points the same as denoted in wiki - so it is maybe just
    > mechanical trick), so by analogy if *(a-1) works a[-1] should be
    > working also


    C is now defined by the ISO document on it. Any writing by
    Ritchie, however much we might enjoy or appreciate it, is no
    longer authoritative.
     
    Tim Rentsch, Dec 20, 2012
    #19
  20. fir

    Tim Rentsch Guest

    Philip Lantz <> writes:

    > Robert Wessel wrote:
    >> fir wrote:
    >> >Can I use c arrays in such way tab[-1] or tab[-1][-1] (I mean when
    >> >index is below zero)?
    >> >
    >> >Also - I think if try to use some way of optimization
    >> >where instead of checking some edge values like
    >> >
    >> >if(x>=0 && x<500 && y>=0 && y<500)
    >> > tab[y][x] = 1;
    >> >
    >> >alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1
    >> >
    >> >but here it would be convenient to cast some pointer to type
    >> >tab[500][500] 'into' wider_tab[502][502] in such way that
    >> >tab[0][0] would correspond to wider_tab[1][1] (and tab[-1][-1]
    >> >to wider_tab[0][0])

    >>
    >>
    >> I think you can do something like this:
    >>
    >> int a[12][12];
    >>
    >> void f()
    >> {
    >> int (*b)[10][12]; // note: use only 0..9 in second index
    >>
    >> b = (int (*)[10][12])&(a[1][1]);
    >>
    >> (*b)[2][2] = 3;
    >> }
    >>
    >> Given that the array layout is standardized, I *think* that doesn't
    >> violate any rules. You'd have a row and column of "pad" around the
    >> 10x10 array.

    >
    > If you don't need to be able to use a negative index in the second
    > dimension, you can do this without a cast, and the behavior is
    > definitely guaranteed:
    >
    > int a[12][12];
    > int (*b)[12] = &a[1];
    >
    > b[-1][0] is a[0][0]
    > b[0][0] is a[1][0]


    Only because the expression being indexed with -1 is of pointer
    type rather than array type.

    >> I'm less confident that using a -1 as an index is guaranteed to work,
    >> but I think it might be.

    >
    > Using -1 as an index in a one-dimensional array is guaranteed to work:
    >
    > int a[12];
    > int *b = &a[1];
    > b[-1] /* This is guaranteed to access a[0]. */


    Again, only because the expression being indexed with -1 is of
    pointer type rather than array type. If b were declared as

    int (*b)[11] = (void*)&a[1];

    then trying to access (*b)[-1] is undefined behavior.


    > With a multi-dimensional array, it is less clear that the behavior is
    > guaranteed when using -1 as an index for anything other than the last
    > dimension,


    Presumably you meant for anything other than the first dimension.

    > but I think it is,


    Any access through an array type must have an index value within
    the bounds of the type of the array. An index value of -1 never
    qualifies.

    > and even if it is not guaranteed by the standard, I believe it
    > is guaranteed by all implementations.


    What I think you mean is that all implementations do in fact
    produce (at the present time) the desired behavior. Even if
    that's true, I expect no implementation actually guarantees it,
    and certainly not all of them do.
     
    Tim Rentsch, Dec 20, 2012
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Hermit Dave
    Replies:
    0
    Views:
    453
    Hermit Dave
    Jan 22, 2004
  2. News Sympatico
    Replies:
    0
    Views:
    318
    News Sympatico
    May 21, 2005
  3. tab 2 into tab 4 ?

    , Jun 19, 2005, in forum: Python
    Replies:
    2
    Views:
    342
  4. HopfZ
    Replies:
    0
    Views:
    302
    HopfZ
    Jan 8, 2007
  5. Andrew Pollock
    Replies:
    1
    Views:
    114
    Captain Paralytic
    Sep 16, 2009
Loading...

Share This Page