Thread: Why does C allow the following construction

  1. #1
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195

    Why does C allow the following construction

    Given something like

    Code:
    #include <stdio.h>
    
    int main(void) {
    
    int arr[2];
    int *p = arr;
    
    return 0;
    }

    Why does C allow a pointer to advance just one beyond the end of the array like the following:

    p = arr +2 ; /*ok*/

    p = arr + 3; /*Not okay*/

    What is the reasoning behind this?

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Here's a better question: What reason would you have for intentionally running off the end of your array?


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    Code:
    char a[8]; 
        char *p; 
    
    
        for ( p = a+1 ; p < a+8 ; p += 2 ) {}

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    No, I didn't say find some stupid way to do it. I said why on earth would you want to?


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User Dante Shamest's Avatar
    Join Date
    Apr 2003
    Posts
    970
    cdalten,

    The real reason is because it doesn't do such buffer overflow checks. C allows you to do that because it assumes the programmer knows what's he's doing. This is what makes C powerful, but and at the same time dangerous to the uncautious programmer.

  6. #6
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    Okay, I guess I'm just not seeing why advancing the pointer one past the array is legal. I don't understand the reasoning behind this. The only part I understand is that allowing the pointer to advance any arbritrary number of points past the end of the array leads to undefined behavior.

  7. #7
    Registered User
    Join Date
    Mar 2006
    Location
    Antwerp, Belgium
    Posts
    9
    Quote Originally Posted by cdalten
    Okay, I guess I'm just not seeing why advancing the pointer one past the array is legal. I don't understand the reasoning behind this. The only part I understand is that allowing the pointer to advance any arbritrary number of points past the end of the array leads to undefined behavior.
    It is just how the memory works and C not checking what you do.
    Let us assume you have 2 arrays which are stored in the memory right next to each other.
    The 1st is 8 characters long, the second one is 3 characters long.
    So if you would move beyond the first array it would end up in the second one.

    It is not a rule that the compiler allows this.
    Although it just depens from the situation.
    In your case I guess it is because you declared the pointer after you declared the variable so that when you go out of bounds the pointer just points to itself, which might perhaps explain why you can only move 1 space out of bounds.
    (Just a guess it could turn out to be all wrong, because this depends, yet again from the situation/compiler,...)
    It could go quite nasty if the memory next to the first array would be like in use by another program or something like that.

    Whenever such a thing happens I get a Fatal exception or a General Processor fault.

    There are 'some' reasons why you could do this but only if you are damn sure everything lies next to each other.
    One example:
    Reading all elements of a multidimensional array or matrix.
    If the arrays are stored next to each other then you can easily read all the elements in the array starting from the primary element.
    E.G:
    matrix a=[[10,2][3,12]] (Sorry for non C syntaxis here)(It is because of my mathematical backround I still think in matrixes instead of multidimensional arrays)
    After storing this in an array and allocating in the memory and if the elements are next to each other you could use your construction to for example get the sum of all the elements.
    =>10, move forward, 2, move forward, ...


    But this is not a healthy thing to do.
    Last edited by Enira; 03-11-2006 at 11:28 AM.

  8. #8
    Registered User
    Join Date
    Jan 2006
    Location
    Berkeley, Ca
    Posts
    195
    Okay, cool. I need a few hours to let this sink in my snoodle. Going off topic, I have nothing better to do today. I called the phone company because I have no dial tone. The said they would send a tech out between 8am and 4pm. They couldn't give me an exact time. Since I'm the only one here, I just have to sit here for the next 8 hours, hoping the tech does show up.

  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Quote Originally Posted by cdalten
    Why does C allow a pointer to advance just one beyond the end of the array
    I think it is to allow this idiom.
    Code:
    #include <stdio.h>
    
    int main(void)
    {
       int *ptr, array[] = {1,2,3,4,5};
       size_t i;
       for ( i = 0; i < sizeof array / sizeof *array; ++i )
       {
          printf("array[%lu] = %d\n", (long unsigned)i, array[i]);
       }
       for ( ptr = array; ptr < array + sizeof array / sizeof *array; ++ptr )
       {
          printf("*ptr = %d\n", *ptr);
       }
       /* rather than requiring */
       for ( ptr = array; ptr <= array + sizeof array / sizeof *array - 1; ++ptr )
       {
          printf("*ptr = %d\n", *ptr);
       }
       return 0;
    }
    The expression array + sizeof array / sizeof *array is one element beyond the array bounds.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  10. #10
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Why does C allow a pointer to advance just one beyond the end of the array
    C requires that arrays have a "past the end" element so that you can use its address as a sentinel:
    Code:
    int a[10];
    int *p = a;
    
    while ( p < &a[10] )
      ++p;
    However, you're not allowed to go further than that, and you're not allowed to dereference the "past the end" element. If you do either, the behavior is undefined.
    My best code is written with the delete key.

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    However, you're not allowed to go further than that
    Why not? As long as you don't dereference the past-the-end element you should be fine. Right? (Not that you'd want to.)
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  12. #12
    Registered User
    Join Date
    Mar 2006
    Location
    Antwerp, Belgium
    Posts
    9
    Code:
    #include <stdio.h>
    #include <conio.h>
    
    int main(void)
    {
       int arr[2];
       int *p = arr;
       
       while(1)
       {
         getch();
         printf("%lu %d\n",++p,*p);
       }
       
    	return 0;
    }
    My DevC++ compiler allows me to move very far.
    Even p = arr + 100; won't crash the application.
    Last edited by Enira; 03-11-2006 at 12:43 PM.

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    "The behavior is undefined": we all know what that means. It works until your customers try to use it.

    [edit]
    getch() is a non-standard function. If you must use it, then include <conio.h>.
    [/edit]
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > Even p = arr + 100; won't crash the application.
    So you've learnt that "doesn't crash" != "bug free".

    Nearly all C implementations allow some form of crappy code which would normally be expected to crash at some point to actually run without problems (initially at least).
    It's only when the programs grow that tolerance for sloppy coding goes down and all the illegal stuff starts producing lots of weird random effects.

  15. #15
    Registered User
    Join Date
    Mar 2006
    Location
    Antwerp, Belgium
    Posts
    9
    Quote Originally Posted by dwks
    [edit]
    getch() is a non-standard function. If you must use it, then include <conio.h>.
    [/edit]
    Was being lazy (exams)
    Seems like 'string.h' gets included too in my compiler(DevC++) as I can use strlen() without including the appropriate header file too.

    God I love being lazy

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. construction order
    By George2 in forum C# Programming
    Replies: 4
    Last Post: 04-30-2008, 08:16 AM
  2. Replies: 29
    Last Post: 12-13-2004, 05:20 PM
  3. construction and induction proofs help
    By axon in forum A Brief History of Cprogramming.com
    Replies: 11
    Last Post: 09-09-2004, 09:02 AM
  4. static members construction
    By glUser3f in forum C++ Programming
    Replies: 3
    Last Post: 11-09-2003, 09:58 PM
  5. OO Compiler construction
    By daljian in forum C++ Programming
    Replies: 0
    Last Post: 01-04-2002, 08:56 AM