end of array

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • subramanian100in@yahoo.com, India

    #1

    end of array

    Suppose we have
    char array[10];

    C allows taking the address of array[10] (ie &array[10] is valid)
    though the element array[10] cannot be accessed.

    Is this allowed for use in binary search method (as given in K & R
    second edition page 137) or is there any other reason ?

  • santosh

    #2
    Re: end of array

    subramanian100i n@yahoo.com, India wrote:
    Suppose we have
    char array[10];
    >
    C allows taking the address of array[10] (ie &array[10] is valid)
    though the element array[10] cannot be accessed.
    >
    Is this allowed for use in binary search method (as given in K & R
    second edition page 137) or is there any other reason ?
    It's allowed because certain idiomatic loop constructs are made easier
    if it was allowed to end up one past an array. The famous strcpy loop
    is an example.

    Comment

    • Cong Wang

      #3
      Re: end of array

      On Mar 4, 12:57 pm, "subramanian10. ..@yahoo.com, India"
      <subramanian10. ..@yahoo.comwro te:
      Suppose we have
      char array[10];
      >
      C allows taking the address of array[10] (ie &array[10] is valid)
      though the element array[10] cannot be accessed.
      >
      Is this allowed for use in binary search method (as given in K & R
      second edition page 137) or is there any other reason ?
      One important facet of C spirit is that "Trust the programmer." C
      gives you the power to do _nearly_ whatever you want (Segment fault or
      something like that is what the OS gives you, not C). C is designed
      for that because it was used to write the Unix kernel originally, this
      niche determines C can't be too complex and can't hide something
      behide programmers.

      You can, of course, use any feature like that freely, but C can't
      guarantee that will be right. Making sure that's right is your work.

      Comment

      • subramanian100in@yahoo.com, India

        #4
        Re: end of array

        It's allowed because certain idiomatic loop constructs are
        made easier
        if it was allowed to end up one past an array. The famous
        strcpy loop is an example.
        Isn't what you have mentioned, an example of pointer ?

        With array, why is it allowed

        Comment

        • santosh

          #5
          Re: end of array

          subramanian100i n@yahoo.com, India wrote:
          It's allowed because certain idiomatic loop constructs are
          made easier
          if it was allowed to end up one past an array. The famous
          strcpy loop is an example.
          >
          Isn't what you have mentioned, an example of pointer ?
          >
          With array, why is it allowed
          Because most often, pointers are used to point to and iterate through
          arrays.

          Comment

          • Daniel Rudy

            #6
            Re: end of array

            At about the time of 3/3/2007 8:57 PM, subramanian100i n@yahoo.com, India
            stated the following:
            Suppose we have
            char array[10];
            >
            C allows taking the address of array[10] (ie &array[10] is valid)
            though the element array[10] cannot be accessed.
            >
            Is this allowed for use in binary search method (as given in K & R
            second edition page 137) or is there any other reason ?
            >
            You can make a pointer point to anything. As to how useful it is...well
            that's up to you.

            I can do this:

            char a[10], *p;
            p = &a[65536];

            p is a pointer, it does point to something, but if I try to use it, then
            I will probably get a segmentation fault or a memory fault. In either
            case, the program will dump core.


            --
            Daniel Rudy

            Email address has been base64 encoded to reduce spam
            Decode email address using b64decode or uudecode -m

            Why geeks like computers: look chat date touch grep make unzip
            strip view finger mount fcsk more fcsk yes spray umount sleep

            Comment

            • santosh

              #7
              Re: end of array

              Daniel Rudy wrote:
              At about the time of 3/3/2007 8:57 PM, subramanian100i n@yahoo.com, India
              stated the following:
              Suppose we have
              char array[10];

              C allows taking the address of array[10] (ie &array[10] is valid)
              though the element array[10] cannot be accessed.

              Is this allowed for use in binary search method (as given in K & R
              second edition page 137) or is there any other reason ?
              >
              You can make a pointer point to anything. As to how useful it is...well
              that's up to you.
              >
              I can do this:
              >
              char a[10], *p;
              p = &a[65536];
              >
              p is a pointer, it does point to something, but if I try to use it, then
              I will probably get a segmentation fault or a memory fault. In either
              case, the program will dump core.
              Not necessarily. The behaviour is undefined if you happen to access
              memory you don't own. Undefined means anything can happen. Under
              modern memory protected OSen, the programme will, as you note, be
              terminated, but under other systems, it could very well keep running,
              but yield wrong results or a system hangup.

              Comment

              • Daniel Rudy

                #8
                Re: end of array

                At about the time of 3/5/2007 7:14 AM, santosh stated the following:
                Daniel Rudy wrote:
                >At about the time of 3/3/2007 8:57 PM, subramanian100i n@yahoo.com, India
                >stated the following:
                >>Suppose we have
                >>char array[10];
                >>>
                >>C allows taking the address of array[10] (ie &array[10] is valid)
                >>though the element array[10] cannot be accessed.
                >>>
                >>Is this allowed for use in binary search method (as given in K & R
                >>second edition page 137) or is there any other reason ?
                >>>
                >You can make a pointer point to anything. As to how useful it is...well
                >that's up to you.
                >>
                >I can do this:
                >>
                >char a[10], *p;
                >p = &a[65536];
                >>
                >p is a pointer, it does point to something, but if I try to use it, then
                >I will probably get a segmentation fault or a memory fault. In either
                >case, the program will dump core.
                >
                Not necessarily. The behaviour is undefined if you happen to access
                memory you don't own. Undefined means anything can happen. Under
                modern memory protected OSen, the programme will, as you note, be
                terminated, but under other systems, it could very well keep running,
                but yield wrong results or a system hangup.
                >
                Of course. I'm thinking in terms of Unix. I guess that on a windows
                system you would get a program error or maybe even a blue-screen. On a
                DOS system, it could keep running depending on what was accessed at that
                location.

                UB = Undefined Behavior = Platform/Implementation specific results.

                And the lesson here folks is don't exceed your defined array dimensions.
                You can kill your program, your system, or worse.

                --
                Daniel Rudy

                Email address has been base64 encoded to reduce spam
                Decode email address using b64decode or uudecode -m

                Why geeks like computers: look chat date touch grep make unzip
                strip view finger mount fcsk more fcsk yes spray umount sleep

                Comment

                • Flash Gordon

                  #9
                  Re: end of array

                  santosh wrote, On 05/03/07 15:14:
                  Daniel Rudy wrote:
                  >At about the time of 3/3/2007 8:57 PM, subramanian100i n@yahoo.com, India
                  >stated the following:
                  >>Suppose we have
                  >>char array[10];
                  >>>
                  >>C allows taking the address of array[10] (ie &array[10] is valid)
                  >>though the element array[10] cannot be accessed.
                  >>>
                  >>Is this allowed for use in binary search method (as given in K & R
                  >>second edition page 137) or is there any other reason ?
                  >>>
                  >You can make a pointer point to anything. As to how useful it is...well
                  >that's up to you.
                  >>
                  >I can do this:
                  >>
                  >char a[10], *p;
                  >p = &a[65536];
                  No you can't. Or rather you can, but since you are doing pointer
                  arithmetic that goes more than 1 past the end of the object the pointer
                  arithmetic invokes undefined behaviour and anything can happen. Note
                  that the [] operator is defined in terms of pointer arithmetic.
                  >p is a pointer, it does point to something, but if I try to use it, then
                  >I will probably get a segmentation fault or a memory fault. In either
                  >case, the program will dump core.
                  >
                  Not necessarily. The behaviour is undefined if you happen to access
                  memory you don't own. Undefined means anything can happen. Under
                  modern memory protected OSen, the programme will, as you note, be
                  terminated, but under other systems, it could very well keep running,
                  but yield wrong results or a system hangup.
                  You don't have to attempt to dereference the pointer to invoke undefined
                  behaviour. Merely calculating a pointer before or more than 1 past the
                  end of an object invokes undefined behaviour even if you do nothing with
                  it. Of course, dereferencing a pointer that does not point to a C object
                  also invokes undefined behaviour that often behaves as you describe,
                  however it is always possible (as far as the C standard is concerned)
                  that instead it will make daemons fly out of your nose.
                  --
                  Flash Gordon

                  Comment

                  • Daniel Rudy

                    #10
                    Re: end of array

                    At about the time of 3/5/2007 7:31 AM, Flash Gordon stated the following:
                    santosh wrote, On 05/03/07 15:14:
                    >Daniel Rudy wrote:
                    >>At about the time of 3/3/2007 8:57 PM, subramanian100i n@yahoo.com, India
                    >>stated the following:
                    >>>Suppose we have
                    >>>char array[10];
                    >>>>
                    >>>C allows taking the address of array[10] (ie &array[10] is valid)
                    >>>though the element array[10] cannot be accessed.
                    >>>>
                    >>>Is this allowed for use in binary search method (as given in K & R
                    >>>second edition page 137) or is there any other reason ?
                    >>>>
                    >>You can make a pointer point to anything. As to how useful it is...well
                    >>that's up to you.
                    >>>
                    >>I can do this:
                    >>>
                    >>char a[10], *p;
                    >>p = &a[65536];
                    >
                    No you can't. Or rather you can, but since you are doing pointer
                    arithmetic that goes more than 1 past the end of the object the pointer
                    arithmetic invokes undefined behaviour and anything can happen. Note
                    that the [] operator is defined in terms of pointer arithmetic.
                    >
                    >>p is a pointer, it does point to something, but if I try to use it, then
                    >>I will probably get a segmentation fault or a memory fault. In either
                    >>case, the program will dump core.
                    >Not necessarily. The behaviour is undefined if you happen to access
                    >memory you don't own. Undefined means anything can happen. Under
                    >modern memory protected OSen, the programme will, as you note, be
                    >terminated, but under other systems, it could very well keep running,
                    >but yield wrong results or a system hangup.
                    >
                    You don't have to attempt to dereference the pointer to invoke undefined
                    behaviour. Merely calculating a pointer before or more than 1 past the
                    end of an object invokes undefined behaviour even if you do nothing with
                    it. Of course, dereferencing a pointer that does not point to a C object
                    also invokes undefined behaviour that often behaves as you describe,
                    however it is always possible (as far as the C standard is concerned)
                    that instead it will make daemons fly out of your nose.
                    Huh?

                    Just calculating a pointer like that can cause UB? How?

                    I thought that the compiler was doing something like this:

                    p = &a[0] + (65536 * sizeof(char));

                    Am I wrong in this assumption?

                    --
                    Daniel Rudy

                    Email address has been base64 encoded to reduce spam
                    Decode email address using b64decode or uudecode -m

                    Why geeks like computers: look chat date touch grep make unzip
                    strip view finger mount fcsk more fcsk yes spray umount sleep

                    Comment

                    • santosh

                      #11
                      Re: end of array


                      Daniel Rudy wrote:
                      At about the time of 3/5/2007 7:31 AM, Flash Gordon stated the following:
                      santosh wrote, On 05/03/07 15:14:
                      Daniel Rudy wrote:
                      >At about the time of 3/3/2007 8:57 PM, subramanian100i n@yahoo.com, India
                      >stated the following:
                      >>Suppose we have
                      >>char array[10];
                      >>>
                      >>C allows taking the address of array[10] (ie &array[10] is valid)
                      >>though the element array[10] cannot be accessed.
                      >>>
                      >>Is this allowed for use in binary search method (as given in K & R
                      >>second edition page 137) or is there any other reason ?
                      >>>
                      >You can make a pointer point to anything. As to how useful it is...well
                      >that's up to you.
                      >>
                      >I can do this:
                      >>
                      >char a[10], *p;
                      >p = &a[65536];
                      No you can't. Or rather you can, but since you are doing pointer
                      arithmetic that goes more than 1 past the end of the object the pointer
                      arithmetic invokes undefined behaviour and anything can happen. Note
                      that the [] operator is defined in terms of pointer arithmetic.
                      >p is a pointer, it does point to something, but if I try to use it, then
                      >I will probably get a segmentation fault or a memory fault. In either
                      >case, the program will dump core.
                      Not necessarily. The behaviour is undefined if you happen to access
                      memory you don't own. Undefined means anything can happen. Under
                      modern memory protected OSen, the programme will, as you note, be
                      terminated, but under other systems, it could very well keep running,
                      but yield wrong results or a system hangup.
                      You don't have to attempt to dereference the pointer to invoke undefined
                      behaviour. Merely calculating a pointer before or more than 1 past the
                      end of an object invokes undefined behaviour even if you do nothing with
                      it. Of course, dereferencing a pointer that does not point to a C object
                      also invokes undefined behaviour that often behaves as you describe,
                      however it is always possible (as far as the C standard is concerned)
                      that instead it will make daemons fly out of your nose.
                      >
                      Huh?
                      >
                      Just calculating a pointer like that can cause UB? How?
                      Yes, since theoretically, an implementation can have different address
                      spaces for each object. So calculating a value beyond one past the
                      object, or before it, could trigger a trap.

                      <snip>

                      Comment

                      • Daniel Rudy

                        #12
                        Re: end of array

                        At about the time of 3/5/2007 8:32 AM, santosh stated the following:
                        Daniel Rudy wrote:
                        >At about the time of 3/5/2007 7:31 AM, Flash Gordon stated the following:
                        >>santosh wrote, On 05/03/07 15:14:
                        >>>Daniel Rudy wrote:
                        >>>>At about the time of 3/3/2007 8:57 PM, subramanian100i n@yahoo.com, India
                        >>>>stated the following:
                        >>>>>Suppose we have
                        >>>>>char array[10];
                        >>>>>>
                        >>>>>C allows taking the address of array[10] (ie &array[10] is valid)
                        >>>>>though the element array[10] cannot be accessed.
                        >>>>>>
                        >>>>>Is this allowed for use in binary search method (as given in K & R
                        >>>>>second edition page 137) or is there any other reason ?
                        >>>>>>
                        >>>>You can make a pointer point to anything. As to how useful it is...well
                        >>>>that's up to you.
                        >>>>>
                        >>>>I can do this:
                        >>>>>
                        >>>>char a[10], *p;
                        >>>>p = &a[65536];
                        >>No you can't. Or rather you can, but since you are doing pointer
                        >>arithmetic that goes more than 1 past the end of the object the pointer
                        >>arithmetic invokes undefined behaviour and anything can happen. Note
                        >>that the [] operator is defined in terms of pointer arithmetic.
                        >>>
                        >>>>p is a pointer, it does point to something, but if I try to use it, then
                        >>>>I will probably get a segmentation fault or a memory fault. In either
                        >>>>case, the program will dump core.
                        >>>Not necessarily. The behaviour is undefined if you happen to access
                        >>>memory you don't own. Undefined means anything can happen. Under
                        >>>modern memory protected OSen, the programme will, as you note, be
                        >>>terminated , but under other systems, it could very well keep running,
                        >>>but yield wrong results or a system hangup.
                        >>You don't have to attempt to dereference the pointer to invoke undefined
                        >>behaviour. Merely calculating a pointer before or more than 1 past the
                        >>end of an object invokes undefined behaviour even if you do nothing with
                        >>it. Of course, dereferencing a pointer that does not point to a C object
                        >>also invokes undefined behaviour that often behaves as you describe,
                        >>however it is always possible (as far as the C standard is concerned)
                        >>that instead it will make daemons fly out of your nose.
                        >Huh?
                        >>
                        >Just calculating a pointer like that can cause UB? How?
                        >
                        Yes, since theoretically, an implementation can have different address
                        spaces for each object. So calculating a value beyond one past the
                        object, or before it, could trigger a trap.
                        >
                        <snip>
                        >
                        I just wrote the following program, and basically it did what it was
                        supposed to do:

                        /*
                        Undefined Behavior Test Program #2
                        */

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

                        int main(void)
                        {
                        char a[10], *p;

                        printf("Here we go...\n");
                        p = &a[65535];
                        printf("We did it. Result is %p\n", (void *)p);
                        return(0);
                        }

                        I got this result:

                        strata:/home/dr2867/c/test 1065 $$$ ->./ub002
                        Here we go...
                        We did it. Result is 0xbfc0ec1f
                        strata:/home/dr2867/c/test 1066 $$$ ->


                        Now for program 2:

                        /*
                        Undefined Behavior Test Program #2
                        */

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

                        int main(void)
                        {
                        char a[10], *p;

                        /* calculate an out of bounds pointer */
                        printf("Here we go...\n");
                        p = &a[65535];
                        printf("We did it. Result is %p\n", (void *)p);

                        /* try and use it */
                        printf("Now we try something else...\n");
                        memcpy(a, p, sizeof(a));
                        printf("How did you like that?\n");
                        return(0);
                        }

                        And this is what I got:

                        strata:/home/dr2867/c/test 1072 $$$ ->./ub002
                        Here we go...
                        We did it. Result is 0xbfc0ec1f
                        Now we try something else...
                        Memory fault (core dumped)
                        strata:/home/dr2867/c/test 1073 $$$ ->


                        This tells me that a pointer is a variable...noth ing more, nothing less.
                        It's a unit of storage in the computer's memory that holds a value
                        regardless of what that location's intended use is. Calculating some
                        junk and putting it there doesn't do anything except put junk at that
                        location (The location of the actual pointer itself, not what it points
                        to.).

                        Now, if you try to use that junk (pointer) for it's intended use of
                        pointing to a memory object, that's when you get undefined behavior.
                        So, looking at what I did, I got a memory fault...also known as a
                        general protection fault to the windows crowd.

                        The lesson here folks is do not access an array beyond it's bounds, and
                        don't go trying to access memory that doesn't belong to you. Your
                        programs and your hairline live much longer.


                        --
                        Daniel Rudy

                        Email address has been base64 encoded to reduce spam
                        Decode email address using b64decode or uudecode -m

                        Why geeks like computers: look chat date touch grep make unzip
                        strip view finger mount fcsk more fcsk yes spray umount sleep

                        Comment

                        • Beej Jorgensen

                          #13
                          Re: end of array

                          Daniel Rudy <ZGNydWR5QHBhY2 JlbGwubmV0wrote :
                          >We did it. Result is 0xbfc0ec1f
                          Here are the relevant parts of the standard that say it's undefined
                          behavior, which means it's totally possible that your implementation
                          could behave exactly as it did. :)

                          C99 6.5.2.1p2, Array subscripting:

                          # A postfix expression followed by an expression in square brackets []
                          # is a subscripted designation of an element of an array object. The
                          # definition of the subscript operator [] is that E1[E2] is identical to
                          # (*((E1)+(E2))). Because of the conversion rules that apply to the
                          # binary + operator, if E1 is an array object (equivalently, a pointer
                          # to the initial element of an array object) and E2 is an integer,
                          # E1[E2] designates the E2-th element of E1 (counting from zero).

                          C99 6.5.6p8, Additive operators:

                          # When an expression that has integer type is added to or subtracted
                          # from a pointer, the result has the type of the pointer operand. If the
                          # pointer operand points to an element of an array object, and the array
                          # is large enough, the result points to an element offset from the
                          # original element such that the difference of the subscripts of the
                          # resulting and original array elements equals the integer expression.
                          # In other words, if the expression P points to the i-th element of an
                          # array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N
                          # (where N has the value n) point to, respectively, the i+n-th and the
                          # i-n-th elements of the array object, provided they exist. Moreover, if
                          # the expression P points to the last element of an array object, the
                          # expression (P)+1 points one past the last element of the array object,
                          # and if the expression Q points one past the last element of an array
                          # object, the expression (Q)-1 points to the last element of the array
                          # object. If both the pointer operand and the result point to elements
                          # of the same array object, or one past the last element of the array
                          # object, the evaluation shall not produce an overflow; otherwise, the
                          # behavior is undefined. If the result points one past the last element
                          # of the array object, it shall not be used as the operand of a unary *
                          # operator that is evaluated.


                          On the other hand, it sounds to me like you're given more leeway to
                          blindly convert an integer to a pointer:

                          C99 6.3.2.3p5, Pointers:

                          # An integer may be converted to any pointer type. Except as previously
                          # specified [NULL pointers], the result is implementation-defined, might
                          # not be correctly aligned, might not point to an entity of the
                          # referenced type, and might be a trap representation.

                          -Beej

                          Comment

                          • christian.bau

                            #14
                            Re: end of array

                            On Mar 5, 4:26 pm, Daniel Rudy <spamt...@spamt his.netwrote:
                            Just calculating a pointer like that can cause UB? How?
                            Because the C Standard says so.

                            #include <stdio.h>

                            #define BAD_VALUE ???

                            size_t test (double *p, size_t n)
                            {
                            double* q;
                            for (q = p; q < p + n; ++q)
                            if (*q == 1.0) return q-p;

                            return 9999;
                            }

                            int main (void)
                            {
                            double a[3] = { 0.0, 1.0, 2.0 };
                            size_t n = BAD_VALUE;

                            if (n >= 2 && test (a, n) == 9999)
                            printf ("Undefined behavior!!!\n") ;

                            return 0;
                            }

                            Can you define BAD_VALUE in such a way that the program prints
                            "Undefined behavior!!!"?

                            Comment

                            • Keith Thompson

                              #15
                              Re: end of array

                              Daniel Rudy <spamthis@spamt his.netwrites:
                              [...]
                              >Daniel Rudy wrote:
                              >>At about the time of 3/5/2007 7:31 AM, Flash Gordon stated the following:
                              [...]
                              >>>You don't have to attempt to dereference the pointer to invoke undefined
                              >>>behaviour. Merely calculating a pointer before or more than 1 past the
                              >>>end of an object invokes undefined behaviour even if you do nothing with
                              >>>it. Of course, dereferencing a pointer that does not point to a C object
                              >>>also invokes undefined behaviour that often behaves as you describe,
                              >>>however it is always possible (as far as the C standard is concerned)
                              >>>that instead it will make daemons fly out of your nose.
                              >>Huh?
                              >>>
                              >>Just calculating a pointer like that can cause UB? How?
                              Calculating a pointer like that *does* cause undefined behavior. The
                              trick is to understand what "undefined behavior" means.
                              I just wrote the following program, and basically it did what it was
                              supposed to do:
                              [snip]
                              And this is what I got:
                              [snip]
                              This tells me that a pointer is a variable...noth ing more, nothing less.
                              No, it doesn't tell you any such thing. The *standard* tells you that
                              performing pointer arithmetic that yields a result that doesn't point
                              either to an element of the array you started from, or just past the
                              last element, invokes undefined behavior -- whether you dereference it
                              or not.

                              One possible consequence of this undefined behavior (and a fairly
                              common one), is that it appears to work.

                              [...]
                              Now, if you try to use that junk (pointer) for it's intended use of
                              pointing to a memory object, that's when you get undefined behavior.
                              So, looking at what I did, I got a memory fault...also known as a
                              general protection fault to the windows crowd.
                              When you computed an invalid pointer value, you got undefined
                              behavior. (It happened to manifest itself quietly.) When you then
                              attempted to dereference that invalid pointer value, you again got
                              undefined behavior. (It happened to manifest itself as a program
                              crash.)

                              Undefined behavior, as defined by C99 3.4.3, is

                              behavior, upon use of a nonportable or erroneous program construct
                              or of erroneous data, for which this International Standard
                              imposes no requirements

                              NOTE Possible undefined behavior ranges from ignoring the
                              situation completely with unpredictable results, to behaving
                              during translation or program execution in a documented manner
                              characteristic of the environment (with or without the issuance of
                              a diagnostic message), to terminating a translation or execution
                              (with the issuance of a diagnostic message).

                              --
                              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."
                              -- Antony Jay and Jonathan Lynn, "Yes Minister"

                              Comment

                              Working...