# Visual Basic > Visual Basic FAQs >  Classic VB - How do I check if array has been initialized?

## Merri

One of the common problems when dealing with arrays is to know when the array has been initialized and when it isn't. Luckily there is an easy native VB code solution:

Not Not ArrayName

What this does is to take the 32-bit pointer value in the array variable, mirror the bits, and then mirror them again. You now effectively know the pointer to the safe array structure. As a side effect you also know whether you can access the array with LBound and UBound.

An example code showing a way to make a new array item:

```
    Dim lngNewIndex As Long
    ' check whether our array is initialized: if it is, take UBound and increase it by one
    If Not Not udtItems Then lngNewIndex = UBound(udtItems) + 1
    ' now change the size of the array
    ReDim Preserve udtItems(lngNewIndex)
```


*Problems & Issues*

There is one major problem: for whatever reason VB IDE does not like this method, and will raise an error in some cases, for example when floating point numbers are coerced to other datatypes. The error does not happen when the program is compiled. Luckily the solution to the issue is short and simple: add this code to run at the beginning of your application.

```
Private Sub Form_Load()
    Dim IDEbug() As Long
    Debug.Assert Not IDEbug Or App.hInstance
End Sub
```

What happens here is that first we make a call to push up the possible error condition. Then we make a call to App.hInstance: we could make a call pretty much to any VB method, but since hInstance returns a Long number we use that. This, for whatever reason, makes all the following Not ArrayName calls work flawlessly. After the line has once executed in the IDE you can even comment the line and it's effects still remain. Only closing VB and opening it again will reset the condition so that you need to make the call again.

Finally, since Debug.Assert will not be compiled into the final executable, you have next to nothing to lose. You only have that one extra line of code that should be executed before getting the array's pointer. (Thanks to Milk for pointing out the App.hInstance, it really simplified this problem a great deal.)


*Bonus code*

Here we have a code that gets the dimensions of an array:

```
Option Explicit

Private Declare Sub GetMem2 Lib "msvbvm60" (Destination As Any, Value As Any)

Public Function ArrayDimensions(ByVal Not_Not_Array As Long) As Integer
    ' have pointer of safe array structure?
    If Not_Not_Array Then
        ' get the dimensions
        GetMem2 ByVal Not_Not_Array, ArrayDimensions
    End If
End Function
```

A sample usage:

```
Private Sub Form_Load()
    Dim lngTest() As Long, lngA As Long
    ' to fix the ide bug
    Debug.Assert Not lngTest Or App.hInstance
    ' put in some dimensions
    ReDim lngTest(1 To 1, 1 To 2, 1 To 3)
    ' loop the dimensions
    For lngA = 1 To ArrayDimensions(Not Not lngTest)
        ' print out the bounds for each dimension
        Debug.Print lngA, LBound(lngTest, lngA), UBound(lngTest, lngA)
    Next lngA
End Sub
```

----------


## Merri

Here is an ArrayInit function for those who just want a simple Boolean value and don't want to bother about the Debug.Assert themselves.



```
Option Explicit

' usage: If ArrayInit(Not ArrayName) Then ...
Public Function ArrayInit(ByVal Not_Array As Long) As Boolean
    ArrayInit = Not (NotValue = -1&)
    Debug.Assert App.hInstance
End Function
```

----------


## yrwyddfa

Here's what I've used for a long time (I didn't know about the Merri method)


VB Code:
Public Type SafeArray1d
    cDims As Integer
    fFeatures As Integer
    cbElements As Long
    cLocks As Long
    pvData As Long
    cElements As Long
    lLbound As Long
End Type
 Public Const ARRAY_NOT_INITIALISED As Long = -1
 Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, source As Any, ByVal Length As Long)
Public Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
  Public Function MaxOrdinal(ppSA As Long) As Long
    
    ' Eg: n = MaxOridinal(VarPtrArray(MyArray))
    
    Dim SA As SafeArray1d
    Dim pSA As Long
     '***********************************************
    '* Deref ppSA. C equivalent: = pSa=*ppSA . . .
    '***********************************************
    CopyMemory pSA, ByVal ppSA, 4
    
    '*****************************************************
    '* If we have a pointer then check to see how
    '* many elements we are allowed. If the array
    '* is not dimensioned then pSA will not be valid . . .
    '*****************************************************
    If pSA Then
        CopyMemory SA, ByVal pSA, LenB(SA)
        MaxOrdinal = (SA.cElements - 1)
    Else
        MaxOrdinal = ARRAY_NOT_INITIALISED
    End If
    
End Function

----------


## Milk

For anyone interested *Not Arrayname* reveals (or not) the inverse of a pointer to the SafeArray structure which VB uses to define arrays. *Not Not Arrayname* returns the actual pointer or 0 if the array is uninitialised.

If you do any kind of Array hacking getting the pointer like this is nice and quick (accounting for the floating point error)

Here is a rather unsafe  :Big Grin:  function which I find useful for when messing with arrays

*Edit:* Safe version added, made more friendly, IDE bug resolved better

```
Option Explicit

Public Type ARRAY_INFORMATION
  Dims As Integer          '00 2 Number of dimensions
  Features As Integer      '02 2 Array construction flags
  ElementSize As Long      '04 4 Size of data elements; 1 byte, 2 integer or boolean, 4 long...
  Locks As Long            '08 4 Number of current locks, a locked Safe Array cannot be redimensioned or destroyed
  DataPtr As Long          '12 4 Data address
  LastDimElements As Long  '16 4 Number of elements in the last dimension
  LastDimLowbound As Long  '20 4 Low bound of the last dimension
End Type

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function IsBadReadPtr Lib "kernel32" (ByVal Pointer As Long, ByVal Length As Long) As Long

Public Function ArrayInfo(ByVal Not_ArrayName As Long) As ARRAY_INFORMATION
'This MUST be called: ArrayInfo(Not arrayname)
'incorrect usage can crash VB, save work before running
   Not_ArrayName = Not Not_ArrayName
   If Not_ArrayName Then CopyMemory ArrayInfo, ByVal Not_ArrayName, 24
   Debug.Assert App.hInstance '<-- this seems to cure the 'Not Array' IDE bug
End Function

Public Function ArrayInfoS(ByVal Not_ArrayName As Long) As ARRAY_INFORMATION
'This should be called: ArrayInfo(Not arrayname)
   Not_ArrayName = Not Not_ArrayName
   If IsBadReadPtr(Not_ArrayName, 24) Then Exit Function
   CopyMemory ArrayInfoS, ByVal Not_ArrayName, 24
   Debug.Assert App.hInstance '<-- this seems to cure the 'Not Array' IDE bug
End Function
```

----------


## Merri

For those interested, Not Not StringArrayName may be the only way to find out the pointer to a string safearray that doesn't require a TLB declared VarPtr function for the job. At least if I recall this correctly, I played with string array hacking sometime last month.

----------


## 7edm

This is an easy way to check if an Array has been initialized, it uses API though:


```
'Module General section
Private Declare Function SafeArrayGetDim Lib "oleaut32.dll" (ByRef saArray() As Any) As Long

'In code
If SafeArrayGetDim(myArray) <> 0 Then
    MsgBox "Array has been Initialized
End If
```

----------


## FireXtol

Another way:


vb Code:
Option Explicit
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Ptr() As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
 Private Function AryIsDimmed(ByVal lArrayPointer As Long) As Boolean
Dim X As Long
CopyMemory X, ByVal lArrayPointer, 4
If X = 0 Then
  AryIsDimmed = False
Else
  AryIsDimmed = True
End If
End Function
 'example usage
Private Sub Form_Load()
Dim X() As Long
Debug.Print AryIsDimmed(VarPtrArray(X))
ReDim X(0)
Debug.Print AryIsDimmed(VarPtrArray(X))
Erase X
Debug.Print AryIsDimmed(VarPtrArray(X))
End Sub

----------


## Merri

```
Dim X() As Long

' ReDim X(1)

If Not Not X Then
    MsgBox "Initialized"
Else
    MsgBox "Not initialized"
End If

Debug.Assert App.hInstance
```


Also to see why Debug.Assert is required in IDE:

```
Option Explicit

Private Sub Form_Load()
    Dim X() As Long
    If Not Not X Then MsgBox "Yay"
    Debug.Assert App.hInstance
    MsgBox CLng(0.1@)
    If Not Not X Then MsgBox "Yay"
    MsgBox CLng(0.1@)
End Sub
```

The second MsgBox will error. Still, performance wise this is the fastest method to check for an initialized array.

----------


## Tech99

Public Function IsArrayInitialized(ByRef arr As Variant) As Boolean
'Is array initialized checking
IsArrayInitialized = False
On Error Resume Next
If UBound(arr) >= 0 Then If Err.Number = 0 Then IsArrayInitialized = True Else Err.Clear
End Function

----------


## scrapersNbots.com

I know this won't apply to all situations but how about
just setting a boolean flag such as   bInitialize, which is declared at
the beginning of the routine.   



```
                            dim  bArrInitialized as boolean
                            dim iArrIndex as integer
```

 Then when needed later in the routine:         



```
                            If bArrInitialized Then
                                      iArrIndex = UBound(Arr) + 1
                                      ReDim Preserve Arr(iArrIndex)
                            Else
                                      bArrInitialized = True
                                      iArrIndex = 0
                                      ReDim Arr(iArrIndex)
                            end if
```


or you can declare the variables at the top of a module and use the code anywhere in the module








> One of the common problems when dealing with arrays is to know when the array has been initialized and when it isn't. Luckily there is an easy native VB code solution:
> 
> Not Not ArrayName
> 
> What this does is to take the 32-bit pointer value in the array variable, mirror the bits, and then mirror them again. You now effectively know the pointer to the safe array structure. As a side effect you also know whether you can access the array with LBound and UBound.
> 
> An example code showing a way to make a new array item:
> 
> ```
> ...

----------

