gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > Bounds-checked arrays

#29088 - sajiimori - Thu Nov 11, 2004 6:59 am

I've been trying to figure out how to implement generic bounds-checked arrays that are as efficient as C arrays (when bounds checking is disabled) and can be initialized during declaration. Here's a naive attempt at such a class:
Code:
template<class T, int SIZE>
class Array
{
    public:
        Array(T data[SIZE]) : mData(data) {}

        T& operator[](int i)
        {
            assert(i >= 0 && i < SIZE);
            return mData[i];
        }

    private:
        T* const mData;
};
At least with GCC, using it involves an extra dereference in comparison to regular arrays. Even if everything is declared const, GCC can't figure out that mData is equivalent to the initializer. So, it seems necessary for the object to actually contain the array, like this:
Code:
template<class T, int SIZE>
class Array
{
    public:
        T& operator[](int i)
        {
            assert(i >= 0 && i < SIZE);
            return mData[i];
        }

    private:
        T mData[SIZE];
};
But how could such an object be initialized during declaration?

Edit: On second thought, the inefficiency of the first version is inconsequential. Since the difference between regular arrays and bounds-checked arrays is only relevant for debug builds, I can simply switch to regular arrays for release builds.

The new questions are: How do I declare the first version gracefully, without having to declare the C array and the wrapper seperately? And then how do I change to standard arrays transparently?

I just know the answer is gonna be "macros", but if there's another way, I'd definitely like to find it.

#29101 - poslundc - Thu Nov 11, 2004 3:15 pm

...

I'd use macros.

I don't know of any other way to toggle invisibly between a native C and foreign C++ construct.

Does it make any difference if you inline the operator method?

Dan.

#29115 - sajiimori - Thu Nov 11, 2004 7:33 pm

It's already inlined in the example.

Here's what I came up with:
Code:
#define DECL_ARRAY(TYPE, NAME, SIZE, ...) \
  TYPE NAME##__c_array[SIZE] = \
  { \
    __VA_ARGS__ \
  }; \
  Array<TYPE, SIZE> NAME(NAME##__c_array)

DECL_ARRAY(int, five_numbers, 5,
  10, 20, 30, 40, 50);
Which expands to:
Code:
int five_numbers__c_array[5] =
{
  10, 20, 30, 40, 50
};
Array<int, 5> five_numbers(five_numbers__c_array);
Improvements?

#29124 - ScottLininger - Thu Nov 11, 2004 10:11 pm

sajiimori wrote:
I just know the answer is gonna be "macros", but if there's another way, I'd definitely like to find it.


What's wrong with macros? I'm a macro junkie. So long as you keep them nicely defined in one spot, they make code much cleaner.

I've often toyed with the idea of making a monstrous macro library that seamlessly allows PHP to become compiled C. ;)

Or are you just doing this as a language exercise and not a practical implementation?

-Scott

#29127 - sajiimori - Thu Nov 11, 2004 11:32 pm

This is for real use.

C macros offend my aesthetic sensibilities, but I don't have time to debate right now.

If you want to turn PHP into C, then write a compiler. If you want to embed PHP into C, then write a preprocessor that invokes your compiler and pastes in the output.