array padding

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • buda

    #1

    array padding

    Hello,
    Is the behaviour of indexing an array with a negative number (like a[-1])
    defined by the standard?


  • Viktor Lofgren

    #2
    Re: array padding

    buda <kulghan@hotmai l.com> wrote:[color=blue]
    > Hello,
    > Is the behaviour of indexing an array with a negative number (like a[-1])
    > defined by the standard?[/color]

    Not 101% certain, but a[n] should point to *(a+(sizeof(*a) *n)), so it should
    be *(a+(sizeof(a)*-1)), that is 1 memory-spot before a starts.

    Comment

    • Martin Dickopp

      #3
      Re: array padding

      "buda" <kulghan@hotmai l.com> writes:
      [color=blue]
      > Is the behaviour of indexing an array with a negative number (like
      > a[-1]) defined by the standard?[/color]

      If the expression refers to an existing array element, then yes.
      Otherwise, the behavior is undefined.

      For example, given the code

      int b [3];
      int *a = b + 1;

      the expression `a [-1]' is valid and refers to the same object as
      `b [0]'.

      Martin


      --
      ,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
      / ,- ) http://www.zero-based.org/ ((_/)o o(\_))
      \ `-' `-'(. .)`-'
      `-. Debian, a variant of the GNU operating system. \_/

      Comment

      • Allin Cottrell

        #4
        Re: array padding

        buda wrote:[color=blue]
        > Hello,
        > Is the behaviour of indexing an array with a negative number (like a[-1])
        > defined by the standard?[/color]

        It's undefined behaviour. See section 6.5.6 of the 1999 C standard.

        Allin Cottrell

        Comment

        • Martin Dickopp

          #5
          Re: array padding

          Viktor Lofgren <root@eudial.no s--pam.mine.nu> writes:
          [color=blue]
          > buda <kulghan@hotmai l.com> wrote:[color=green]
          >> Hello,
          >> Is the behaviour of indexing an array with a negative number (like
          >> a[-1]) defined by the standard?[/color]
          >
          > Not 101% certain, but a[n] should point to *(a+(sizeof(*a) *n)),[/color]

          Your statement is misleading. First of all, `a [n]' is not necessarily
          a pointer, so it's not necessarily pointing to anything. You probably
          mean "the address of `a [n]' is the same as ...".

          More importantly, the address of `a [n]' is the same as the address of
          `*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
          `sizeof *a' happens to be 1. However the address of `a [n]' is the same
          as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
          of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.

          Martin


          --
          ,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
          / ,- ) http://www.zero-based.org/ ((_/)o o(\_))
          \ `-' `-'(. .)`-'
          `-. Debian, a variant of the GNU operating system. \_/

          Comment

          • Viktor Lofgren

            #6
            Re: array padding

            Martin Dickopp <expires-2004-06-30@zero-based.org> wrote:[color=blue]
            > More importantly, the address of `a [n]' is the same as the address of
            > `*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
            > `sizeof *a' happens to be 1. However the address of `a [n]' is the same
            > as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
            > of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.[/color]

            No, if a is int_32*, a[n] = *(a + 4 * n).
            For an example:

            int* b = NULL;
            printf("%d %d", &b[0], &b[1]);

            prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".

            Comment

            • Christian Bau

              #7
              Re: array padding

              In article <2wRrc.85$dx3.1 112@newsb.telia .net>,
              Viktor Lofgren <root@eudial.no s--pam.mine.nu> wrote:
              [color=blue]
              > Martin Dickopp <expires-2004-06-30@zero-based.org> wrote:[color=green]
              > > More importantly, the address of `a [n]' is the same as the address of
              > > `*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
              > > `sizeof *a' happens to be 1. However the address of `a [n]' is the same
              > > as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
              > > of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.[/color]
              >
              > No, if a is int_32*, a[n] = *(a + 4 * n).
              > For an example:
              >
              > int* b = NULL;
              > printf("%d %d", &b[0], &b[1]);
              >
              > prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".[/color]

              I suggest you try

              int a [10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
              int n = 1;

              printf ("%d %d\n", a [n], * (a + 4 * n));

              and tell us what happens.

              Comment

              • Martin Dickopp

                #8
                Re: array padding

                Viktor Lofgren <root@eudial.no s--pam.mine.nu> writes:
                [color=blue]
                > Martin Dickopp <expires-2004-06-30@zero-based.org> wrote:[color=green]
                >> More importantly, the address of `a [n]' is the same as the address of
                >> `*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
                >> `sizeof *a' happens to be 1. However the address of `a [n]' is the same
                >> as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
                >> of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.[/color]
                >
                > No, if a is int_32*, a[n] = *(a + 4 * n).[/color]

                No. Please look up in your C book what the effect of the `+' operator
                is if one operand is a pointer and the other is an integer.
                [color=blue]
                > For an example:
                >
                > int* b = NULL;
                > printf("%d %d", &b[0], &b[1]);
                >
                > prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".[/color]

                This code fragment invokes undefined behavior for two reasons: First of
                all, the "%d" specifier expects an `int' argument, but `&b[0]' and
                `&b[1]' have type `int *'. Secondly, it is undefined behavior to add
                something to a null pointer, as is done in the expression `&b[1]'.

                Since the code invokes undefined behavior, anything could have happened,
                including printing "0 4", printing "0 1", or printing a Shakespearean
                sonnet.

                If you really want a program that demonstrates that you're wrong, try
                this one:


                #include <stdio.h>

                int main (void)
                {
                int a [4];
                printf ("address of a [1] is %p\n", (void *)&a [1]);
                printf ("address of *(a + 1) is %p\n", (void *)&*(a + 1));
                printf ("address of *(a + 4 * 1) is %p\n", (void *)&*(a + 4 * 1));
                return 0;
                }


                Martin


                --
                ,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
                / ,- ) http://www.zero-based.org/ ((_/)o o(\_))
                \ `-' `-'(. .)`-'
                `-. Debian, a variant of the GNU operating system. \_/

                Comment

                • Gordon Burditt

                  #9
                  Re: array padding

                  >> More importantly, the address of `a [n]' is the same as the address of[color=blue][color=green]
                  >> `*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
                  >> `sizeof *a' happens to be 1. However the address of `a [n]' is the same
                  >> as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
                  >> of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.[/color]
                  >
                  >No, if a is int_32*, a[n] = *(a + 4 * n).[/color]

                  No. I think you mean a[n] = *(a addl (4 mull n))
                  where addl and mull are assembly-language arithmetic operators.
                  [color=blue]
                  >For an example:
                  >
                  > int* b = NULL;
                  > printf("%d %d", &b[0], &b[1]);
                  >
                  >prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".[/color]

                  C operators are different from assembly-language ones, especially
                  when pointers are involved.

                  Also, there is no guarantee that sizeof(a 32-bit integer type) does not
                  equal 1.

                  Gordon L. Burditt

                  Comment

                  • Stephen L.

                    #10
                    Re: array padding

                    Allin Cottrell wrote:[color=blue]
                    >
                    > buda wrote:[color=green]
                    > > Hello,
                    > > Is the behaviour of indexing an array with a negative number (like a[-1])
                    > > defined by the standard?[/color]
                    >
                    > It's undefined behaviour. See section 6.5.6 of the 1999 C standard.
                    >
                    > Allin Cottrell[/color]

                    Maybe you could give us a wee bit more to go on...
                    Since we might be looking at two different documents,
                    are you refering to the section titled -

                    "6.5.6 Additive operators"?

                    I'm not sure how the following is "undefined behaviour"...

                    /*************** *************** **************/

                    #include <stdio.h>


                    int
                    main()
                    {
                    char str[] = "1234567890 ";
                    char *p = &str[ sizeof (str) - 1 ]; /* `p' points to string's
                    NULL */


                    printf("Charact er should be '0', '%c'.\n", p[ -1 ]);
                    printf("Charact er should be '9', '%c'.\n", p[ -2 ]);

                    printf("Charact er should be '0', '%c'\n", *(p - 1));
                    printf("Charact er should be '9', '%c'\n", *(p - 2));

                    printf("Same as above, '0', '%c'.\n", *--p); /* Is _this_ undefined
                    too? */
                    printf("Same as above, '9', '%c'.\n", *--p);

                    return (0);
                    }


                    --
                    Stephen

                    Comment

                    • Arthur J. O'Dwyer

                      #11
                      Re: array padding


                      On Sat, 22 May 2004, Stephen L. wrote:[color=blue]
                      >
                      > Allin Cottrell wrote:[color=green]
                      > > buda wrote:[color=darkred]
                      > > > Is the behaviour of indexing an array with a negative number (like a[-1])
                      > > > defined by the standard?[/color]
                      > >
                      > > It's undefined behaviour. See section 6.5.6 of the 1999 C standard.[/color]
                      >
                      > I'm not sure how the following is "undefined behaviour"...[/color]

                      It's not. However, if 'a' is, as the OP said, an array name, then
                      indeed indexing 'a' with a negative subscript will dereference a pointer
                      that's not pointing to an object. E.g.,

                      foo a[bar]; a[-1];

                      is *always*, without exception, undefined behavior.

                      Doing the same thing with a pointer, e.g.

                      baz *p = quux; p[-1];

                      may or may not invoke UB, depending on the value of 'quux'. In your
                      example, there is no undefined behavior.

                      -Arthur

                      [color=blue]
                      > #include <stdio.h>
                      >
                      > int
                      > main()
                      > {
                      > char str[] = "1234567890 ";
                      > char *p = &str[ sizeof (str) - 1 ]; /* `p' points to string's
                      > NULL */
                      >
                      >
                      > printf("Charact er should be '0', '%c'.\n", p[ -1 ]);
                      > printf("Charact er should be '9', '%c'.\n", p[ -2 ]);
                      >
                      > printf("Charact er should be '0', '%c'\n", *(p - 1));
                      > printf("Charact er should be '9', '%c'\n", *(p - 2));
                      >
                      > printf("Same as above, '0', '%c'.\n", *--p); /* Is _this_ undefined
                      > too? */
                      > printf("Same as above, '9', '%c'.\n", *--p);
                      >
                      > return (0);
                      > }[/color]

                      Comment

                      • Martin Dickopp

                        #12
                        Re: array padding

                        "Stephen L." <sdlnospamar@ca st-com.net> writes:
                        [color=blue]
                        > char str[] = "1234567890 ";
                        > char *p = &str[ sizeof (str) - 1 ]; /* `p' points to string's
                        > NULL */[/color]

                        ITYM null character instead of NULL. (NULL is a macro which expands to
                        a null /pointer/ constant.)

                        Martin


                        --
                        ,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
                        / ,- ) http://www.zero-based.org/ ((_/)o o(\_))
                        \ `-' `-'(. .)`-'
                        `-. Debian, a variant of the GNU operating system. \_/

                        Comment

                        • Chris Torek

                          #13
                          Re: array padding

                          In article <news:2wRrc.85$ dx3.1112@newsb. telia.net>
                          Viktor Lofgren <root@eudial.no s--pam.mine.nu> writes:[color=blue]
                          >For an example:
                          >
                          > int* b = NULL;
                          > printf("%d %d", &b[0], &b[1]);
                          >
                          >prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".[/color]

                          I ran this on a Data General Eclipse[%] and it printed:

                          1879048192 1879048194

                          Can you explain this?

                          (Convert the above to hex for a big hint. The numbers are 0x70000000
                          and 0x70000002 respectively. The facts that sizeof(int) is 4 and
                          that "int *" uses "word pointers", with 16-bit words, are both
                          important.)

                          [% Actually I do not have access to one, but this is what it might
                          print, if I remember right. I made up a segment-and-ring number
                          of 0x7 and am not sure that this is correct for user-mode code, or
                          even the right number of bits.]
                          --
                          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.

                          Comment

                          • Keith Thompson

                            #14
                            Re: array padding

                            "buda" <kulghan@hotmai l.com> writes:[color=blue]
                            > Hello,
                            > Is the behaviour of indexing an array with a negative number (like a[-1])
                            > defined by the standard?[/color]

                            If a is an array object, then evaluating a[-1] invokes undefined
                            behavior.

                            Array indexing is really a binary operation ("binary" meaning it takes
                            two operands); the left operand is a pointer to some object type, and
                            the right operand is an integer (or vice versa; see below). x[y] is
                            equivalent to *(x+y). Since x is a pointer and y is an integer, the
                            "+" performs pointer arithmetic.

                            If "a" points into the middle of an array object, "a[-1]" yields the
                            value of the array element just before the one that "a" points to.

                            It may seem odd that the left operand is expected to be a pointer, not
                            an array. It works for arrays because, in most expression contexts,
                            an array name is converted to a pointer to its first element.

                            (x[y] is equivalent to *(x+y). Since addition is commutative, *(x+y)
                            is equivalent to *(y+x), which is equivalent to y[x]. Thus
                            5["abcdef"] is a legal expression, equal to 'f'. This is interesting,
                            but not particularly useful.)

                            See section 6 of the C FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
                            for more information. While you're there, read the whole thing.

                            --
                            Keith Thompson (The_Other_Keit h) kst-u@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.

                            Comment

                            • Charles Richmond

                              #15
                              Re: array padding

                              buda wrote:[color=blue]
                              >
                              > Hello,
                              > Is the behaviour of indexing an array with a negative number (like a[-1])
                              > defined by the standard?
                              >[/color]
                              You can do something like the following;

                              #include <stdio.h>
                              #include <stdlib.h>

                              int main()
                              {
                              int *a, *b;

                              b = malloc(21 * sizeof int);

                              a = b + 11;

                              a[5] = 42;

                              a[-5] = 24;

                              printf("The values are %d and %d\n",a[5],a[-5]);
                              }

                              This technique can be useful when converting a Pascal program
                              that is using negative subscripts.




                              --
                              +----------------------------------------------------------------+
                              | Charles and Francis Richmond richmond at plano dot net |
                              +----------------------------------------------------------------+

                              Comment

                              Working...