← Back to context

Comment by layer8

18 hours ago

> no array bounds checking is possible.

This isn’t strictly true, a C implementation is allowed to associate memory-range (or more generally, pointer provenance) metadata with a pointer.

The DeathStation 9000 features a conforming C implementation which is known to catch all array bounds violations. ;)

Right. Also it might it sound like array-to-pointer decay is forced onto the programmer. Instead, you can take the address of an array just fine without letting it decay. The type then preserves the length.

  • C: int foo(int a[]) { return a[5]; }

        int main() {
            int a[3];
            return foo(a);
        }
    
        > gcc test.c
        > ./a.out

    Oops.

    D: int foo(int[] a) { return a[5]; }

        int main() {
            int[3] a;
            return foo(a);
        }
    
        > ./cc array.d
        > ./array
        core.exception.ArrayIndexError@array.d(1): index [5] is out of bounds for array of length 3
    

    Ah, Nirvana!

    How to fix it for C:

    https://www.digitalmars.com/articles/C-biggest-mistake.html

    • You need to take the address of the array instead of letting it decay and then size is encoded in the type:

        int foo(int (*a)[6]) { return a[5]; }
        int main() {
        int a[3];
          return foo(&a);
        }
      

      Or for run-time length:

        int foo(int n, int (*a)[n]) { return (\*a)[5]; }
        int main() {
          int a[3];
          return foo(ARRAY_SIZE(a), &a);
        }
        /app/example.c:4:38: runtime error: index 5 out of bounds for 
       type 'int[n]'
      

      https://godbolt.org/z/dxx7TsKbK\*