0

What's difference between

Len(Me.txtStartDate.Value & vbNullString) = 0

and

Len(Me.txtStartDate.Value) = 0
litelite
  • 2,857
  • 4
  • 23
  • 33
Drinkwater
  • 23
  • 1
  • 1
  • 6
  • 1
    `Len(Me.txtStartDate.Value & vbNullString) = 0` is equivalent to doing `Len(Me.txtStartDate.Value & "") = 0`. The only reason i could see why someone would do that is to make sure that the value is text before passing it to `Len` because `Len` raise an error if you pass it a raw number. – litelite Sep 01 '17 at 19:21
  • 1
    Related: [Is there any difference between vbNullString and “”?](https://stackoverflow.com/q/32435320/4934172). – 41686d6564 stands w. Palestine Sep 01 '17 at 19:30

3 Answers3

4

vbNullString is essentially a null string pointer.

Debug.Print StrPtr(vbNullString) 'prints 0

It looks equivalent to a literal "" empty string, but it's not:

Debug.Print StrPtr("") 'prints an address; 6 bytes are allocated for it

There is practically no difference between your two examples... but only because Me.txtStartDate.Value is already a String.

If you were doing this:

Debug.Print Sheet1.Range("A1").Value & vbNullString

Then you would be doing an implicit type conversion between whatever type is returned by Sheet1.Range("A1").Value (say, a Date, or a Double) by means of string concatenation, because the & operator is only used for string concatenations, and the result of that expression will be a String.

In other words, it's a rather convoluted way to do this:

Debug.Print CStr(Sheet1.Range("A1").Value)

Or, as litelite mentioned, a rather convoluted way to do this:

Len(CStr(Me.txtStartDate.Value)) = 0

You typically use vbNullString in place of an empty string "" literal, to spare uselessly allocating 6 bytes (4 for the string pointer, 2 for the null character), and to make your code unambiguously clear about your intent (e.g. "I mean an empty string, this wasn't a typo"), similar to how you would use string.Empty in C#.

Mathieu Guindon
  • 69,817
  • 8
  • 107
  • 235
  • You don't really save memory since a `vbNullString` needs at least 16 bytes (4 bytes null pointer + 12 ansi chars) compared to 12 for "" (4 bytes pointer + 6 bytes bstr + 2 ansi chars). Since all the strings are mapped in a dictionary, you'll probably end up using more space with a `vbNullString`. It's just my personal opinion, but I find `""` less ambiguous since it makes clear that it's a string of length 0. – Florent B. Sep 01 '17 at 20:48
  • @FlorentB. fair enough. FWIW I'd warmly recommend `vbNullString` over `""` for the exact same reasons `string.Empty` is preferred over `""` in .net. The memory argument is pretty much moot, no computer is going to run short of memory for over-allocating empty strings - it's all for readability/maintainability. [string.Empty vs ""](https://stackoverflow.com/q/151472/1188513) – Mathieu Guindon Sep 01 '17 at 20:52
  • I would agree with you if `vbNullString` was called `vbEmptyString`. The word null can be confusing especially since there's also `vbNullChar` which is a string of length 1. [Null-References-The-Billion-Dollar-Mistake-Tony-Hoare](https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare) – Florent B. Sep 01 '17 at 21:09
2

What is vbNullString? It is one strange bird, which exists solely for calling functions in a DLL that were written in C (or C++).

Take a look at http://vb.mvps.org/tips/varptr/. It describes a set of (now hidden) functions in VBA (and VB6) that exist solely to allow the passing of pointers to the contents of variables, again mostly to functions in a DLL that were written in C (or any other language that does pointers).

(Technically, VBA does not do pointers, so any pointer that may be returned by a function is - technically speaking - casted to a long integer. ByRef and With do involve pointers, of course, but in hidden-behind-the-scene ways.)

In particular, try out StrPtr(vbNullString); it will return 0. If you tried instead StrPtr(""), you would get some non-zero result. The result is a pointer to where the characters of a string really are in memory. However, a pointer of 0 means something special in C (and C++) - it is often called the NULL pointer (or simply NULL, or maybe null), and it is meant to signify that a pointer points to nowhere. In C programming, sometimes a coder would like to allow a pointer parameter being NULL to mean something special for a function.

If you tried StrPtr("") a few times in a row, you'll likely get a few different non-zero results. That's because VBA is creating a brand new empty string for each try, and as weird as it seems that any memory should be used for a string that is empty, remember that a string in VBA includes a long integer that indicates the number of characters in the string.

rskar
  • 4,607
  • 25
  • 21
0

Ok guys my 2 cents on the old topic which has been commented on many times.

First vbNullString and vbNullChar are constants, names of some bytes already allocated in memory. That is why when you use vbNullString instead of "" it indeed saves some bytes memory because "" will allocate an empty string, at least temporarily, which also takes some cpu cycles.

You may try for yourself. Using vbNullString is 3x faster.

Private Declare PtrSafe Function QueryPerformanceFrequency _
    Lib "kernel32.dll" (ByRef lpPFreq As Currency _
) As Boolean

Private Declare PtrSafe Function QueryPerformanceCounter _
    Lib "kernel32.dll" (ByRef lpPCount As Currency _
) As Boolean

Sub Test()
    Dim t0 As Currency, t As Currency, f As Currency
    Dim s As String
    Dim i As Long
    
    QueryPerformanceFrequency f
    
    QueryPerformanceCounter t0
    For i = 1 To 10 ^ 6
        s = ""
    Next
    QueryPerformanceCounter t
    Debug.Print 1000 * (t - t0) / f; "ms"
    
    QueryPerformanceCounter t0
    For i = 1 To 10 ^ 6
        s = vbNullString
    Next
    QueryPerformanceCounter t
    Debug.Print 1000 * (t - t0) / f; "ms"

End Sub

The vbNullString constant is a String which can be easily proven by trying:

Debug.print LenB(vbNullstring) ' prints 0
Debug.print VarPtr(vbNullstring) ' prints 8 (= vbString)

The vbNullChar constant is also a string. Try:

Debug.print LenB(vbNullChar) ' prints 2
Debug.print VarPtr(vbNullChar) ' print 8 (= vbString)

Which will print 2 (= 2 bytes) and 8 (vbString).

Secondly vbNullString is thus not a pointer. VB/VBA doesn't do pointers so a null pointer constant is not defined.

However, I use pointers a lot and therefore I define:

Const vbNullPtr As LongPtr = 0
Debug.print VarPtr(vbNullPtr ) ' print 20 (x64) and 4 (x32)

So using vbNullString instead of vbNullPtr works correctly when dealing with pointers because VB/VBA converts automatically. However, it is not very neat.

So further straightforward points about the vbNullString beast.

Debug.Print StrPtr(vbNullString) ' prints 0

Likewise:

Dim s as String
Debug.Print StrPtr(s) 'prints 0

Here s is a string variable holding the 0 address. After a string is allocated the StrPtr(s) will be the BSTR pointer.

Dim s as String: v = ""
Debug.Print StrPtr(s) ' prints BSTR address

Now the string variable stores the address of the allocated BSTR which holds 0 bytes but needs 6 bytes to hold the BSTR structure.

Let me know what you think. This may all be somewhat futile but I like to get things right.

Tyler2P
  • 2,324
  • 26
  • 22
  • 31