473,418 Members | 2,083 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,418 software developers and data experts.

Outdated help (feat. Access '97 and VB4)

Hello,
I'm working at a simple Access '97 + VB4 application, and I ran into a
terrible problem: something I never modified now gives me a totally
unwanted "Invalid use of null" error.
It happens in a Text.LostFocus event, this block:

Do While Not TB6.EOF
If Year(TB6(0)) = Val(Trim(Text1.Text)) Then
!!!!!!!!!!!!!Here!!!!!!!!!
...
bla bla bla
...
End If

Where TB6 is a table. The text in Text1 is compared to the Year taken
out of the first colum in TB6. Checking the database itself, I have
entries for 2002, 2002, 2003, 2005... and up to this morning everything
worked so good. Now, it only works ok for 2005, while other values are
considered to be null and error creeps in.
Any idea? I really don't know what to do.
Thanks!
ZDS

Dec 13 '05 #1
43 2173
If Text1.Text is NULL, then how can you trim it?

Try this ...

Val(Trim(Text1.Text & ""))

This will force the NULL to an empty string, which can be trimmed.

--

Danny J. Lesandrini
dl*********@hotmail.com
http://amazecreations.com/datafast
"ZillionDollarSadist" <ca*******@gmail.com> wrote ...
Hello,
I'm working at a simple Access '97 + VB4 application, and I ran into a
terrible problem: something I never modified now gives me a totally
unwanted "Invalid use of null" error.
It happens in a Text.LostFocus event, this block:

Do While Not TB6.EOF
If Year(TB6(0)) = Val(Trim(Text1.Text)) Then
!!!!!!!!!!!!!Here!!!!!!!!!
...
bla bla bla
...
End If

Where TB6 is a table. The text in Text1 is compared to the Year taken
out of the first colum in TB6. Checking the database itself, I have
entries for 2002, 2002, 2003, 2005... and up to this morning everything
worked so good. Now, it only works ok for 2005, while other values are
considered to be null and error creeps in.
Any idea? I really don't know what to do.
Thanks!
ZDS

Dec 13 '05 #2
Mmmh, I think I didn't explain myself enough. Text1.Text is never
empty. But Year(TB6(0)) is, and it shouldn't - its value is taken from
an Access table where there's a date in column 0. The fact is, column 0
is never empty. It has lots of entries for 2001, 2002, 2003 and some
for 2005. And only the latter ones, NOW, are considered not null.
Totally absurd since a few hours ago it all worked ok and I didn't
change anything related to this..
ZDS

Dec 13 '05 #3
Yeah, I guess I completely ignored that part, since it didn't make the
least bit of sense to me. What does that syntax reference? An array?

Year(TB6(0))

So, is TB6() and array and you want element zero? Is it a variant
array? If so, then TB6(0) is NULL and you have to handle that.

Year(Nz(TB6(0),0))
--

Danny J. Lesandrini
dl*********@hotmail.com
http://amazecreations.com/datafast
"ZillionDollarSadist" <ca*******@gmail.com> wrote ...
Mmmh, I think I didn't explain myself enough. Text1.Text is never
empty. But Year(TB6(0)) is, and it shouldn't - its value is taken from
an Access table where there's a date in column 0. The fact is, column 0
is never empty. It has lots of entries for 2001, 2002, 2003 and some
for 2005. And only the latter ones, NOW, are considered not null.
Totally absurd since a few hours ago it all worked ok and I didn't
change anything related to this..
ZDS

Dec 13 '05 #4
TB6(0) is column 0 of a database table. And you know what? I created
for error another column, so that there was an empty new column in
position 0...
Thanks anyway for your patience!
ZDS

Dec 13 '05 #5
"Danny J. Lesandrini" <dl*********@hotmail.com> wrote in
news:pu******************************@giganews.com :
If Text1.Text is NULL, then how can you trim it?

Try this ...

Val(Trim(Text1.Text & ""))

This will force the NULL to an empty string, which can be trimmed.


And I believe it's always best to use vbNullString in place of an
empty string.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Dec 13 '05 #6
I've never tried that. (There are many things I've never tried.)
Is it faster or simply more bullet proof?

--
Danny J. Lesandrini

"David W. Fenton" <dX********@bway.net.invalid> wrote ...

And I believe it's always best to use vbNullString in place of an
empty string.

Dec 13 '05 #7
"Danny J. Lesandrini" <dl*********@hotmail.com> wrote in
news:cZ********************@giganews.com:
"David W. Fenton" <dX********@bway.net.invalid> wrote ...

And I believe it's always best to use vbNullString in place of an
empty string.


I've never tried that. (There are many things I've never tried.)
Is it faster or simply more bullet proof?


Well, the way I see it, there are two issues:

1. it's a pre-declared constant. Memory has already been allocated
for it. If you use "" inline in code, memory has to be allocated for
that. For a single line, well, that's going to be insignificant, but
in extensive loops, or in functions used in queries, it could be
quite significant.

2. it's easier to read code that uses vbNullString than "", because
one might encounter the latter and ask "what happened to the
string?" When you use the named constant, you are declaring very
precisely with no ambiguity that you're using a zero-length string.

--
David W. Fenton http://www.dfenton.com/
dfenton at bway dot net http://www.dfenton.com/DFA/
Dec 14 '05 #8
David W. Fenton wrote:
"Danny J. Lesandrini" <dl*********@hotmail.com> wrote in
news:cZ********************@giganews.com:
"David W. Fenton" <dX********@bway.net.invalid> wrote ...
And I believe it's always best to use vbNullString in place of an
empty string.

I've never tried that. (There are many things I've never tried.)
Is it faster or simply more bullet proof?


Well, the way I see it, there are two issues:

1. it's a pre-declared constant. Memory has already been allocated
for it. If you use "" inline in code, memory has to be allocated for
that. For a single line, well, that's going to be insignificant, but
in extensive loops, or in functions used in queries, it could be
quite significant.

2. it's easier to read code that uses vbNullString than "", because
one might encounter the latter and ask "what happened to the
string?" When you use the named constant, you are declaring very
precisely with no ambiguity that you're using a zero-length string.


Run this in Access 2003. Which is fastest? Which is slowest? If you have
time, please report back so that we can confirm our results.

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Const iterations As Long = 1000000
Sub temp()
Dim r As String
Dim s As String
Dim t As Long
Dim u As Long
r = "P P"

Debug.Print "" = vbNullString
Debug.Print "" = s
Debug.Print s = vbNullString
Debug.Print
Debug.Print VarPtr(vbNullString)
Debug.Print VarPtr(s)
Debug.Print VarPtr("")
Debug.Print
Debug.Print StrPtr(vbNullString)
Debug.Print StrPtr(s)
Debug.Print StrPtr("")
Debug.Print

t = GetTickCount
For u = 1 To iterations
If InStr(r, vbNullString) <> 0 Then
End If
Next u
Debug.Print "vbnullstring " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
If InStr(r, s) <> 0 Then
End If
Next u
Debug.Print "unitialized string " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
If InStr(r, "") <> 0 Then
End If
Next u
Debug.Print "literal " & Chr(34) & Chr(34) & " " & GetTickCount - t

End Sub

******

Another strange thing is that "" and vbnullstring have the same varptr,
which indicates that they are the same thing. But they don't have the
same strptr which indicates that they are not the same thing.

--
Lyle Fairfield
Dec 14 '05 #9
Here's what I got ...

vbnullstring 109
unitialized string 109
literal "" 109

--
Danny J. Lesandrini
dl*********@hotmail.com
http://amazecreations.com/datafast
"Lyle Fairfield" <ly***********@aim.com> wrote ...

Run this in Access 2003. Which is fastest? Which is slowest? If you have time, please report back so that we can
confirm our results.
.... --
Lyle Fairfield

Dec 14 '05 #10
Lyle Fairfield <ly***********@aim.com> wrote in
news:gF****************@read2.cgocable.net:
Run this in Access 2003. Which is fastest? Which is slowest?


We went through this before.

In any event, this particular code isn't actually testing use of ""
vs. vbNullstring in a loop. You would want to compare these two:

Dim strTmp As String

For i = 1 To 10000 Step 1
strTmp = cstr(i) & ""
Next i

Dim strTmp As String

For i = 1 To 10000 Step 1
strTmp = cstr(i) & vbNullstring
Next i

Or calling Nz() with "" as the IfNull argument as opposed to
vbNullstring.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Dec 14 '05 #11
"Danny J. Lesandrini" <dl*********@hotmail.com> wrote in
news:2s******************************@giganews.com :
Here's what I got ...

vbnullstring 109
unitialized string 109
literal "" 109


Lyle's tests have zilch to do with the point I made.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Dec 14 '05 #12
David W. Fenton wrote:
Lyle Fairfield <ly***********@aim.com> wrote in
news:gF****************@read2.cgocable.net:
Run this in Access 2003. Which is fastest? Which is slowest?


We went through this before.

In any event, this particular code isn't actually testing use of ""
vs. vbNullstring in a loop. You would want to compare these two:

Dim strTmp As String

For i = 1 To 10000 Step 1
strTmp = cstr(i) & ""
Next i

Dim strTmp As String

For i = 1 To 10000 Step 1
strTmp = cstr(i) & vbNullstring
Next i

Or calling Nz() with "" as the IfNull argument as opposed to
vbNullstring.


You're right.

Option Explicit

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Const iterations As Long = 1000000
Sub temp()
Dim q As String
Dim r As String
Dim s As String
Dim t As Long
Dim u As Long
r = " P "

Debug.Print "" = vbNullString
Debug.Print "" = s
Debug.Print s = vbNullString
Debug.Print
Debug.Print VarPtr(vbNullString)
Debug.Print VarPtr(s)
Debug.Print VarPtr("")
Debug.Print
Debug.Print StrPtr(vbNullString)
Debug.Print StrPtr(s)
Debug.Print StrPtr("")
Debug.Print

t = GetTickCount
For u = 1 To iterations
q = Val(Trim(r & vbNullString))
Next u
Debug.Print "vbnullstring " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
q = Val(Trim(r & s))
Next u
Debug.Print "unitialized string " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
q = Val(Trim(r & ""))
Next u
Debug.Print "literal " & Chr(34) & Chr(34) & " " & GetTickCount - t

End Sub
--
Lyle Fairfield
Dec 15 '05 #13
rkc
David W. Fenton wrote:
"Danny J. Lesandrini" <dl*********@hotmail.com> wrote in
news:2s******************************@giganews.com :

Here's what I got ...

vbnullstring 109
unitialized string 109
literal "" 109

Lyle's tests have zilch to do with the point I made.


The only point you have is readability.
I'd say that's good enough even though the name sucks.

Dec 15 '05 #14
> strange thing is that "" and vbnullstring have the same varptr,
indicates that they are the same thing. But they don't have the strptr
which indicates that they are not the same thing.
That is, they both (at different times) use the same dynamically
allocated memory to point to a string space, but the string space
they point to is different.

The traditional explanation is that vbNullString points to
an existing null string space, but "" points to a dynamically
created null string space.

I can't see it myself: defining "" as vbNullString is such
an obvious step that I find it hard to believe they are
interpreted differently by the interpreter.

(david)
"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:gF****************@read2.cgocable.net... David W. Fenton wrote:
"Danny J. Lesandrini" <dl*********@hotmail.com> wrote in
news:cZ********************@giganews.com:
"David W. Fenton" <dX********@bway.net.invalid> wrote ...
And I believe it's always best to use vbNullString in place of an
empty string.
I've never tried that. (There are many things I've never tried.)
Is it faster or simply more bullet proof?


Well, the way I see it, there are two issues:

1. it's a pre-declared constant. Memory has already been allocated
for it. If you use "" inline in code, memory has to be allocated for
that. For a single line, well, that's going to be insignificant, but
in extensive loops, or in functions used in queries, it could be
quite significant. 2. it's easier to read code that uses vbNullString
than "", because
one might encounter the latter and ask "what happened to the
string?" When you use the named constant, you are declaring very
precisely with no ambiguity that you're using a zero-length string.


Run this in Access 2003. Which is fastest? Which is slowest? If you have
time, please report back so that we can confirm our results.

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Const iterations As Long = 1000000
Sub temp()
Dim r As String
Dim s As String
Dim t As Long
Dim u As Long
r = "P P"

Debug.Print "" = vbNullString
Debug.Print "" = s
Debug.Print s = vbNullString
Debug.Print
Debug.Print VarPtr(vbNullString)
Debug.Print VarPtr(s)
Debug.Print VarPtr("")
Debug.Print
Debug.Print StrPtr(vbNullString)
Debug.Print StrPtr(s)
Debug.Print StrPtr("")
Debug.Print

t = GetTickCount
For u = 1 To iterations
If InStr(r, vbNullString) <> 0 Then
End If
Next u
Debug.Print "vbnullstring " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
If InStr(r, s) <> 0 Then
End If
Next u
Debug.Print "unitialized string " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
If InStr(r, "") <> 0 Then
End If
Next u
Debug.Print "literal " & Chr(34) & Chr(34) & " " & GetTickCount - t

End Sub

******

Another strange thing is that "" and vbnullstring have the same varptr,
which indicates that they are the same thing. But they don't have the same
strptr which indicates that they are not the same thing.

--
Lyle Fairfield

Dec 15 '05 #15
david epsom dot com dot au wrote:
strange thing is that "" and vbnullstring have the same varptr,
indicates that they are the same thing. But they don't have the strptr
which indicates that they are not the same thing.


That is, they both (at different times) use the same dynamically
allocated memory to point to a string space, but the string space
they point to is different.

The traditional explanation is that vbNullString points to
an existing null string space, but "" points to a dynamically
created null string space.


"david" points to a string pointer. The string pointer points to a
memory location. In the four bytes before the memory location we find
the long, ten. At the memory location we find a unicode representation
of "david".

"" points to a string pointer. The string pointer points to a memory
location. In the four bytes before the memory location we find the long,
zero. At the memory location we find nothing.

"david" and "" are identical, AFAICT, except in content.

But vbNullstring is something else.

vbnullstring points to the same string pointer as "". But it never gets
there. (I find this confusing and have no explanation for it). Because
its string pointer is zero. There is no string to which it points. So
there is no memory being set aside for it, exisitng or prexisting. [In
fact, regardless of the return of vartype or typename I don't consider
vbnullstring to be a vba string. It has no memory and it has no length,
(which len munges as zero). But no length and zero length are not the
same things.]

A declared but uninitialized string, s, is similar to vbnullstring
except that it does not point to a string pointer. Its var pointer and
its string pointer are both zero.

I agree with David and rkc that using VbNullString is good coding
practice as it helps with reading and understanding the code.

I suspect there may be a minimal advantage in speed to using
vbnullstring or an unitilialized string over using "". But I can't
confirm that consistently.

It's quite possible that VBA creates temporary variables for the storage
of other manifestations of these strings and non-string depending upon
its requirements or the things we are asking it to do, and so this may
not be the whole story.

--
Lyle Fairfield
Dec 15 '05 #16
varptr tells us where the variable is located in memory, strptr tells us
where the string buffer is located.

So we can realistically forget varptr and concentrate on what strptr is
telling us.

Strptr for a "" returns a value, i.e. memory has been set aside to hold the
contents of the string (even though it is a zero length string). strptr for
vbNullString returns 0, so ther eis no memory allocated for vbNullStrings
value.

So the advantages of vbNullString are:-
1) readability
2) It's more memory efficient as no memory is allocated for what is in
essence an empty string.

I'm convinced <g>.
--
Terry Kreft

"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:6z****************@read1.cgocable.net...
david epsom dot com dot au wrote:
strange thing is that "" and vbnullstring have the same varptr,
indicates that they are the same thing. But they don't have the strptr
which indicates that they are not the same thing.


That is, they both (at different times) use the same dynamically
allocated memory to point to a string space, but the string space
they point to is different.

The traditional explanation is that vbNullString points to
an existing null string space, but "" points to a dynamically
created null string space.


"david" points to a string pointer. The string pointer points to a memory
location. In the four bytes before the memory location we find the long,
ten. At the memory location we find a unicode representation of "david".

"" points to a string pointer. The string pointer points to a memory
location. In the four bytes before the memory location we find the long,
zero. At the memory location we find nothing.

"david" and "" are identical, AFAICT, except in content.

But vbNullstring is something else.

vbnullstring points to the same string pointer as "". But it never gets
there. (I find this confusing and have no explanation for it). Because its
string pointer is zero. There is no string to which it points. So there is
no memory being set aside for it, exisitng or prexisting. [In fact,
regardless of the return of vartype or typename I don't consider
vbnullstring to be a vba string. It has no memory and it has no length,
(which len munges as zero). But no length and zero length are not the same
things.]

A declared but uninitialized string, s, is similar to vbnullstring except
that it does not point to a string pointer. Its var pointer and its string
pointer are both zero.

I agree with David and rkc that using VbNullString is good coding practice
as it helps with reading and understanding the code.

I suspect there may be a minimal advantage in speed to using vbnullstring
or an unitilialized string over using "". But I can't confirm that
consistently.

It's quite possible that VBA creates temporary variables for the storage
of other manifestations of these strings and non-string depending upon its
requirements or the things we are asking it to do, and so this may not be
the whole story.

--
Lyle Fairfield

Dec 15 '05 #17
Here's my story and I'm sticking with it forever or until you show me
my error, whichever comes first:

"" and vbNullString both have the same VarPtr, on my computer, 1308268.

This should point to their StrPtr.

It does for "". That is at memory location 1308268 I find a long, viz,
1684888 which is the StrPtr for "".

But it is not the StrPtr for vbNullString (the StrPtr of vbNullString
is zero). I think it should be the StrPtr for vbNullString. Ergo, I
say, "vbNullString is not a string, in the sense that "", or "Terry" is
a string.

Dec 15 '05 #18
rkc <rk*@rochester.yabba.dabba.do.rr.bomb> wrote in
news:mE*******************@twister.nyroc.rr.com:
David W. Fenton wrote:
"Danny J. Lesandrini" <dl*********@hotmail.com> wrote in
news:2s******************************@giganews.com :

Here's what I got ...

vbnullstring 109
unitialized string 109
literal "" 109

Lyle's tests have zilch to do with the point I made.


The only point you have is readability.


No, there's a potential performance benefit in loops. I didn't come
up with this idea myself -- it was MichKa who repeatedly used to
make this recommendation back when he still posted here.

And Lyle's test doesn't address that at all.
I'd say that's good enough even though the name sucks.


There's anotther named constant for the same thing, but I've
forgotten its name.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Dec 15 '05 #19
rkc
Lyle Fairfield wrote:
Here's my story and I'm sticking with it forever or until you show me
my error, whichever comes first:

"" and vbNullString both have the same VarPtr, on my computer, 1308268.

This should point to their StrPtr.

It does for "". That is at memory location 1308268 I find a long, viz,
1684888 which is the StrPtr for "".

But it is not the StrPtr for vbNullString (the StrPtr of vbNullString
is zero). I think it should be the StrPtr for vbNullString. Ergo, I
say, "vbNullString is not a string, in the sense that "", or "Terry" is
a string.


The help file specifically states that vbNullString is not the same as
a zero length string. But then it also says it's a string having a value
of 0, whatever the hell that means. It also says it is meant to be used
when calling outside functions, as in API calls and other such libraries
I would assume. I'm not sure why I started using it with Len().
Probably because I saw M. Kaplan recommend it as dwf did.
Dec 15 '05 #20
Okay, I think we're actually close to agreement, except that you believe
that vbNullString is not a string purely because it doesn't point to a
memory location. I on the other hand do not believe that is a restriction
on a variable being of string type.

Consider the following code

Option Explicit

Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" ( _
ByRef Destination As Any, _
ByVal Length As Long _
)

Sub TestString()
Dim a As String
Dim b As String

a = vbNullString
b = ""
Debug.Print VarPtr(a), StrPtr(a), VarPtr(b), StrPtr(b)
Call ZeroMemory(b, 4)
Debug.Print VarPtr(a), StrPtr(a), VarPtr(b), StrPtr(b)
Debug.Print StrComp(a, "", vbBinaryCompare), StrComp(a, vbNullString,
vbBinaryCompare)
Debug.Print StrComp(b, "", vbBinaryCompare), StrComp(b, vbNullString,
vbBinaryCompare)
Debug.Print VarType(a) = vbString, VarType(b) = vbString

End Sub

When I run this code I get the following results

TestString
1308396 0 1308392 55204876
1308396 0 1308392 0
0 0
0 0
True True

From this we see that line 1 gives us what we have seen before i.e. a
pointer to the memory location of the variable the pointer to the variable
data for a (vbNullString) is 0 but is a valid memory address for b ("").

When we zero the memory for b ("") and check the varptr and the strptr we
now see that "" and vbNullString return functionally similar results, i.e. a
memory address for the variable but a 0 for the location of the data.

We then see that comparing a and b to vbNullstring and "" returns equality
in all cases and also that the variable type is still string.

Therefore vbNullString is a string but it simply has no data QED

To fully understand what is said below a review of the structure of strings
in VB(A) might be useful.

Essentially string variables in VB (post VB3) are what is called a basic
string (BSTR). The variable actually contains a pointer to a memory
location where the data for the string is held, this string is null
terminated. The four bytes just before the memory location pointed to,
holds data which tells us how big the block of memory used to hold the
string is. So, in the extract from Bruce McKinney, when he talks about the
empty BSTR and he refers to the single null character to the right of the
address he is talking about the Null character which terminates the empty
string, when he talks about the long integer containing zero he is talking
about the memory location which tells us how long the string is (i.e. it has
zero length).

If we look in the MSDN we get confirmation that this is the case. Now I'm
using the MSDN from October 2001 so I can't give
online references, but in the article "Strings the OLE Way" by Bruce
McKinney April 18, 1996 we read:-

"Rule 8: A null pointer is the same as an empty string to a BSTR.
Experienced C++ programmers will find this concept startling because it
certainly isn't true of normal C++ strings. An empty BSTR is a pointer to a
zero-length string. It has a single null character to the right of the
address being pointed to, and a long integer containing zero to the left. A
null BSTR is a null pointer pointing to nothing. There can't be any
characters to the right of nothing, and there can't be any length to the
left of nothing. Nevertheless, a null pointer is considered to have a length
of zero ..."
Also in the Platform SDK: Automation in the topic String Manipulation
Functions we have:-
"A null pointer is a valid value for a BSTR variable. By convention, it is
always treated the same as a pointer to a BSTR that contains zero
characters."
We can see what is happening with an empty string by the following code

Option Explicit

Private Declare Sub CopyMemory _
Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)

Sub TestString2()
Dim b As String
Dim c() As Byte
Dim lngSize As Long
Dim lngStrLocn As Long
Dim lngSizeLocn As Long
Dim intCount As Integer

b = "a"

lngStrLocn = StrPtr(b)

lngSizeLocn = lngStrLocn - 4

Call CopyMemory(lngSize, ByVal lngSizeLocn, 4)

ReDim c(1 To lngSize + 2)

Call CopyMemory(c(1), ByVal b, lngSize + 2)

Debug.Print "Variable b = '" & b & "'"
Debug.Print "================="
Debug.Print "String", "Size", "String"
Debug.Print "Location", "Location", "Length"
Debug.Print "---------", "---------", "-------"
Debug.Print lngStrLocn, lngSizeLocn, lngSize
For intCount = 1 To lngSize + 2
Debug.Print "Element " & intCount & " ="; c(intCount)
Next

b = ""

lngStrLocn = StrPtr(b)

lngSizeLocn = lngStrLocn - 4

Call CopyMemory(lngSize, ByVal lngSizeLocn, 4)

ReDim c(1 To lngSize + 2)

Call CopyMemory(c(1), ByVal b, lngSize + 2)

Debug.Print
Debug.Print "Variable b = '" & b & "'"
Debug.Print "================="
Debug.Print "String", "Size", "String"
Debug.Print "Location", "Location", "Length"
Debug.Print "---------", "---------", "-------"
Debug.Print lngStrLocn, lngSizeLocn, lngSize

For intCount = 1 To lngSize + 2
Debug.Print "Element " & intCount & " ="; c(intCount)
Next
End Sub

On my machine this displays
Variable b = 'a'
=================
String Size String
Location Location Length
--------- --------- -------
2361516 2361512 2
Element 1 = 97
Element 2 = 0
Element 3 = 0
Element 4 = 0

Variable b = ''
=================
String Size String
Location Location Length
--------- --------- -------
54536428 54536424 0
Element 1 = 0
Element 2 = 0
Conclusion
==========
vbNullString is a pointer to a Null memory location
"" is a pointer to a memory location which contains a Null character to the
right and 4 bytes of memory preceding it which contains the value zero.

In OLE a BSTR which contains a Null pointer is treated by convention the
same as an empty string.

and so we come back to what I said before, the difference between them is:-
1) vbNullString makes the code more readable.
2) vbNullString takes up less memory (6 bytes) than "".

I'm hoping I can say now; "Gosh that forever went by pretty quick ...".

Hmm, it's hard to gloat while the universe is ending <BG>.
--
Terry Kreft

"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
Here's my story and I'm sticking with it forever or until you show me
my error, whichever comes first:

"" and vbNullString both have the same VarPtr, on my computer, 1308268.

This should point to their StrPtr.

It does for "". That is at memory location 1308268 I find a long, viz,
1684888 which is the StrPtr for "".

But it is not the StrPtr for vbNullString (the StrPtr of vbNullString
is zero). I think it should be the StrPtr for vbNullString. Ergo, I
say, "vbNullString is not a string, in the sense that "", or "Terry" is
a string.


Dec 16 '05 #21
Well explained! Thanks.

Dec 16 '05 #22
No, thank you Lyle. I learned some interesting things while researching
that.

e.g. I now fully understand why you should use vbNullString instead of "" in
API calls.

Good exchange of views I enjoyed it.
--
Terry Kreft

"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:11**********************@g43g2000cwa.googlegr oups.com...
Well explained! Thanks.

Dec 16 '05 #23
"Terry Kreft" <te*********@mps.co.uk> wrote in
news:zc********************@karoo.co.uk:
e.g. I now fully understand why you should use vbNullString
instead of "" in API calls.


Whould say there is no reason to prefer it to "" in pure VBA loops?

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Dec 16 '05 #24
I think there is a word missing. I'm taking it that what you meant to write
was:-
Would you say there is no reason to prefer it to "" in pure VBA loops?
--
If you are saying do I believe there is a performance advantage to assigning
vbNullString to a string variable in a loop rather than assigning "" then I
would say there alsmost certainly is.

If you assign "" to a string variable then we know that 6 bytes of memory is
having to be written every time, together with all the system resources that
such an assignment implies. Assigning vbNullstring means that all that
should need happen is at worst a release of memory, which really should be
more efficient than assignment.

There is the factor that 6 bytes of memory is being used, which is
unnecessary, but I would have thought this to be trivial unless of course a
large number strings are being used.

Woukd the user notice a performance increase using vbNullString? I doubt
it.

Caveat, the above response is pure speculation.

--
Terry Kreft

"David W. Fenton" <XX*******@dfenton.com.invalid> wrote in message
news:Xn**********************************@127.0.0. 1...
"Terry Kreft" <te*********@mps.co.uk> wrote in
news:zc********************@karoo.co.uk:
e.g. I now fully understand why you should use vbNullString
instead of "" in API calls.


Whould say there is no reason to prefer it to "" in pure VBA loops?

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/

Dec 17 '05 #25
Terry Kreft wrote:
--
If you are saying do I believe there is a performance advantage to assigning
vbNullString to a string variable in a loop rather than assigning "" then I
would say there alsmost certainly is.


Option Explicit

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Const iterations As Long = 1000000

Sub temp()
Dim q As String
Dim r As String
Dim s As String
Dim t As Long
Dim u As Long
r = " P "

Debug.Print "--------"
t = GetTickCount
For u = 1 To iterations
q = Val(Trim(r & vbNullString))
Next u
Debug.Print "vbNullString " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
q = Val(Trim(r & s))
Next u
Debug.Print "unitialized string " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
q = Val(Trim(r & ""))
Next u
Debug.Print "literal " & Chr(34) & Chr(34) & " " & GetTickCount - t
Debug.Print "--------"
End Sub

Sub temp2()
Dim z As Long
For z = 0 To 9
temp
Next z
End Sub

--------
vbNullString 1572
unitialized string 1392
literal "" 1382
--------
--------
vbNullString 1382
unitialized string 1392
literal "" 1392
--------
--------
vbNullString 1392
unitialized string 1372
literal "" 1392
--------
--------
vbNullString 1382
unitialized string 1372
literal "" 1372
--------
--------
vbNullString 1392
unitialized string 1382
literal "" 1382
--------
--------
vbNullString 1392
unitialized string 1392
literal "" 1382
--------
--------
vbNullString 1362
unitialized string 1372
literal "" 1362
--------
--------
vbNullString 1392
unitialized string 1392
literal "" 1372
--------
--------
vbNullString 1382
unitialized string 1392
literal "" 1382
--------
--------
vbNullString 1392
unitialized string 1392
literal "" 1372
--------
Application name Microsoft Access
Version 11.0
Build 6566
Product ID 70145-OEM-5790133-51068
Application path C:\Program Files\Microsoft Office\OFFICE11\
Language English (United States)
ADO version 2.8
VBA version 6.04
References VBA, Access, stdole, ADODB, DAO
Database name tests.mdb
Database path C:\Documents and Settings\Lyle Fairfield\My
Documents\Access
Database size 796.0 KB
Database create date 2005-12-07 21:00:09
Current user Admin
Jet version 4.0

OS Name Microsoft Windows XP Home Edition
Version 5.1.2600 Service Pack 2 Build 2600
OS Manufacturer Microsoft Corporation
System Name FFDBA
System Manufacturer Sony Corporation
System Model VGN-A150(UC)
System Type X86-based PC
Processor x86 Family 6 Model 13 Stepping 6 GenuineIntel ~1495 Mhz
BIOS Version/Date American Megatrends Inc. R0080F1, 2004-09-28
SMBIOS Version 2.3
Windows Directory C:\WINDOWS
System Directory C:\WINDOWS\system32
Boot Device \Device\HarddiskVolume2
Locale Canada
Hardware Abstraction Layer Version = "5.1.2600.2180
(xpsp_sp2_rtm.040803-2158)"
User Name FFDBA\Lyle Fairfield
Time Zone Eastern Standard Time
Total Physical Memory 512.00 MB
Available Physical Memory 88.12 MB
Total Virtual Memory 2.00 GB
Available Virtual Memory 1.96 GB
Page File Space 1.22 GB
Page File C:\pagefile.sys

Dec 17 '05 #26
Upon rereading I want to ask one question.

"" is a pointer to a memory location which contains a Null character
to the
right and 4 bytes of memory preceding it which contains the value zero.
To the right of the memory location we find a null character,
represented by zero.

If there were no null character to the right of the memory location,
what would we expect to find there?

Dec 17 '05 #27
Lyle I believe Terry stated that a difference would be noticeable in
assigning a variable to vbNullString over "". Since a string Var not
initialized is the same as vbNullString:

vbNullString 46
unitialized string 47
literal "" 203
--------
--------

Private Declare Function GetTickCount Lib "kernel32" () As Long

Private Const iterations As Long = 1000000
Private Sub Command0_Click()
On Error GoTo Err_Command0_Click

'Sub temp()
Dim q As String
Dim r As String
Dim s As String
Dim t As Long
Dim u As Long
Dim lRet As Long
r = " P "

Debug.Print "--------"
t = GetTickCount
For u = 1 To iterations
'q = Val(Trim(r & vbNullString))
q = vbNullString
'lRet = Len(r & vbNullString)
Next u
Debug.Print "vbNullString " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
'q = Val(Trim(r & s))
q = s
'lRet = Len(r & s)
Next u
Debug.Print "unitialized string " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
'q = Val(Trim(r & ""))
q = ""
'lRet = Len(r & "")
Next u
Debug.Print "literal " & Chr(34) & Chr(34) & " " & GetTickCount - t
Debug.Print "--------"
Exit_Command0_Click:
Exit Sub

Err_Command0_Click:
MsgBox Err.Description
Resume Exit_Command0_Click

End Sub


--

HTH
Stephen Lebans
http://www.lebans.com
Access Code, Tips and Tricks
Please respond only to the newsgroups so everyone can benefit.
"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:11*********************@g49g2000cwa.googlegro ups.com...
Terry Kreft wrote:
--
If you are saying do I believe there is a performance advantage to
assigning
vbNullString to a string variable in a loop rather than assigning "" then
I
would say there alsmost certainly is.


Option Explicit

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Const iterations As Long = 1000000

Sub temp()
Dim q As String
Dim r As String
Dim s As String
Dim t As Long
Dim u As Long
r = " P "

Debug.Print "--------"
t = GetTickCount
For u = 1 To iterations
q = Val(Trim(r & vbNullString))
Next u
Debug.Print "vbNullString " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
q = Val(Trim(r & s))
Next u
Debug.Print "unitialized string " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
q = Val(Trim(r & ""))
Next u
Debug.Print "literal " & Chr(34) & Chr(34) & " " & GetTickCount - t
Debug.Print "--------"
End Sub

Sub temp2()
Dim z As Long
For z = 0 To 9
temp
Next z
End Sub

--------
vbNullString 1572
unitialized string 1392
literal "" 1382
--------
--------
vbNullString 1382
unitialized string 1392
literal "" 1392
--------
--------
vbNullString 1392
unitialized string 1372
literal "" 1392
--------
--------
vbNullString 1382
unitialized string 1372
literal "" 1372
--------
--------
vbNullString 1392
unitialized string 1382
literal "" 1382
--------
--------
vbNullString 1392
unitialized string 1392
literal "" 1382
--------
--------
vbNullString 1362
unitialized string 1372
literal "" 1362
--------
--------
vbNullString 1392
unitialized string 1392
literal "" 1372
--------
--------
vbNullString 1382
unitialized string 1392
literal "" 1382
--------
--------
vbNullString 1392
unitialized string 1392
literal "" 1372
--------
Application name Microsoft Access
Version 11.0
Build 6566
Product ID 70145-OEM-5790133-51068
Application path C:\Program Files\Microsoft Office\OFFICE11\
Language English (United States)
ADO version 2.8
VBA version 6.04
References VBA, Access, stdole, ADODB, DAO
Database name tests.mdb
Database path C:\Documents and Settings\Lyle Fairfield\My
Documents\Access
Database size 796.0 KB
Database create date 2005-12-07 21:00:09
Current user Admin
Jet version 4.0

OS Name Microsoft Windows XP Home Edition
Version 5.1.2600 Service Pack 2 Build 2600
OS Manufacturer Microsoft Corporation
System Name FFDBA
System Manufacturer Sony Corporation
System Model VGN-A150(UC)
System Type X86-based PC
Processor x86 Family 6 Model 13 Stepping 6 GenuineIntel ~1495 Mhz
BIOS Version/Date American Megatrends Inc. R0080F1, 2004-09-28
SMBIOS Version 2.3
Windows Directory C:\WINDOWS
System Directory C:\WINDOWS\system32
Boot Device \Device\HarddiskVolume2
Locale Canada
Hardware Abstraction Layer Version = "5.1.2600.2180
(xpsp_sp2_rtm.040803-2158)"
User Name FFDBA\Lyle Fairfield
Time Zone Eastern Standard Time
Total Physical Memory 512.00 MB
Available Physical Memory 88.12 MB
Total Virtual Memory 2.00 GB
Available Virtual Memory 1.96 GB
Page File Space 1.22 GB
Page File C:\pagefile.sys

Dec 17 '05 #28
The actual string data. And in that case the 4 bytes would describe a long
value representing the length of the string data. I have not read this whole
thread but we are talking about BSTR's here aren't you?

--

HTH
Stephen Lebans
http://www.lebans.com
Access Code, Tips and Tricks
Please respond only to the newsgroups so everyone can benefit.
"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:11*********************@g14g2000cwa.googlegro ups.com...
Upon rereading I want to ask one question.

"" is a pointer to a memory location which contains a Null character
to the
right and 4 bytes of memory preceding it which contains the value zero.
To the right of the memory location we find a null character,
represented by zero.

If there were no null character to the right of the memory location,
what would we expect to find there?

Dec 17 '05 #29
rkc
Stephen Lebans wrote:
Lyle I believe Terry stated that a difference would be noticeable in
assigning a variable to vbNullString over "". Since a string Var not
initialized is the same as vbNullString:


The original claim by dwf was concatenating a string (or Null as in the
case of a control with no value) with VbNullString is faster. There is
essentially no difference in that case.
Dec 17 '05 #30

Not enough iterations and I think Val and Trim may cause some masking

The results below suggest that vbNullstring is fastest, than an empty string
followed by an uninitialised string.

I find it surprising that the unitialised string appears to be the slowest.

Anyway overall who would really care about such a minimal difference, which
at
1000000 (your original iteration) doesn't even show up.
Option Explicit

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Const iterations As Long = 10000000

Sub temp()
Dim q As String
Dim r As String
Dim s As String
Dim t As Long
Dim u As Long
r = " P "

Debug.Print "--------"
t = GetTickCount
For u = 1 To iterations
q = r & vbNullString
Next u
Debug.Print "vbNullString " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
q = r & s
Next u
Debug.Print "unitialized string " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
q = r & ""
Next u
Debug.Print "literal " & Chr(34) & Chr(34) & " " & GetTickCount - t
Debug.Print "--------"
End Sub

Sub temp2()
Dim z As Long
For z = 0 To 9
temp
Next z
End Sub

Results
===========
--------
vbNullString 3765
unitialized string 3926
literal "" 3785
--------
--------
vbNullString 3716
unitialized string 3975
literal "" 3776
--------
--------
vbNullString 3755
unitialized string 3966
literal "" 3765
--------
--------
vbNullString 3736
unitialized string 3935
literal "" 3786
--------
--------
vbNullString 3735
unitialized string 3956
literal "" 3755
--------
--------
vbNullString 3756
unitialized string 3915
literal "" 3786
--------
--------
vbNullString 3735
unitialized string 3946
literal "" 3785
--------
--------
vbNullString 3716
unitialized string 3945
literal "" 3816
--------
--------
vbNullString 3705
unitialized string 3926
literal "" 3785
--------
--------
vbNullString 3706
unitialized string 3965
literal "" 3785
--------

--
Terry Kreft

"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:11*********************@g49g2000cwa.googlegro ups.com...
Terry Kreft wrote:
--
If you are saying do I believe there is a performance advantage to
assigning
vbNullString to a string variable in a loop rather than assigning "" then
I
would say there alsmost certainly is.


Option Explicit

<SNIP>
Dec 17 '05 #31
Hi Stephen,
Long time no talk <g>.

As rkc says David was originally talking about concatenation but I think
your test below is more in line with what I was thinking about when I
replied to David.

This certainly sems to show a significant relative difference between
assignment (as opposed to concatenation) of a Null string compared to an
empty string.

Aha, this maybe shows why.

Sub Wassup()
Dim r As String
Dim s As String
Dim u As Long

Const iteration = 4

Debug.Print "Concatenate """" string"
Debug.Print "--------------------------------"
For u = 1 To iteration
r = r & ""
Debug.Print VarPtr(r), StrPtr(r)
Next
Debug.Print "Assign """" string"
Debug.Print "--------------------------------"
For u = 1 To iteration
r = ""
Debug.Print VarPtr(r), StrPtr(r)
Next
Debug.Print "Assign vbNullString string"
Debug.Print "--------------------------------"
For u = 1 To iteration
r = vbNullString
Debug.Print VarPtr(r), StrPtr(r)
Next
Debug.Print "Concatenate vbNullString string"
Debug.Print "--------------------------------"
For u = 1 To iteration
r = r & vbNullString
Debug.Print VarPtr(r), StrPtr(r)
Next

Debug.Print "Assign Null String string"
Debug.Print "--------------------------------"
For u = 1 To iteration
r = s
Debug.Print VarPtr(r), StrPtr(r)
Next
Debug.Print "Concatenate Null String string"
Debug.Print "--------------------------------"
For u = 1 To iteration
r = r & s
Debug.Print VarPtr(r), StrPtr(r)
Next
End Sub

Results
======
Concatenate "" string
--------------------------------
1308536 138404036
1308536 138331180
1308536 138404036
1308536 138331180
Assign "" string
--------------------------------
1308536 138404036
1308536 138331180
1308536 138404036
1308536 138331180
Assign vbNullString string
--------------------------------
1308536 0
1308536 0
1308536 0
1308536 0
Concatenate vbNullString string
--------------------------------
1308536 138404036
1308536 138767612
1308536 138404036
1308536 138767612
Assign Null String string
--------------------------------
1308536 0
1308536 0
1308536 0
1308536 0
Concatenate Null String string
--------------------------------
1308536 138404036
1308536 138331180
1308536 138404036
1308536 138331180

Summary
=======
Whenever we concatenate a string the memory location of the data changes.

When we assign an initialised string the meory location changes.

When we assign a Null string the memory location doesn't change (because
it's null).
--
Terry Kreft

"Stephen Lebans" <ForEmailGotoMy.WebSite.-WWWdotlebansdot...@linvalid.com>
wrote in message news:np**********************@ursa-nb00s0.nbnet.nb.ca...
Lyle I believe Terry stated that a difference would be noticeable in
assigning a variable to vbNullString over "". Since a string Var not
initialized is the same as vbNullString:

vbNullString 46
unitialized string 47
literal "" 203
--------
--------

Private Declare Function GetTickCount Lib "kernel32" () As Long

Private Const iterations As Long = 1000000
Private Sub Command0_Click()
On Error GoTo Err_Command0_Click

'Sub temp()
Dim q As String
Dim r As String
Dim s As String
Dim t As Long
Dim u As Long
Dim lRet As Long
r = " P "

Debug.Print "--------"
t = GetTickCount
For u = 1 To iterations
'q = Val(Trim(r & vbNullString))
q = vbNullString
'lRet = Len(r & vbNullString)
Next u
Debug.Print "vbNullString " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
'q = Val(Trim(r & s))
q = s
'lRet = Len(r & s)
Next u
Debug.Print "unitialized string " & GetTickCount - t

t = GetTickCount
For u = 1 To iterations
'q = Val(Trim(r & ""))
q = ""
'lRet = Len(r & "")
Next u
Debug.Print "literal " & Chr(34) & Chr(34) & " " & GetTickCount - t
Debug.Print "--------"
Exit_Command0_Click:
Exit Sub

Err_Command0_Click:
MsgBox Err.Description
Resume Exit_Command0_Click

End Sub


--

HTH
Stephen Lebans
http://www.lebans.com
Access Code, Tips and Tricks
Please respond only to the newsgroups so everyone can benefit.
"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:11*********************@g49g2000cwa.googlegro ups.com...
Terry Kreft wrote:
<SNIP>

Dec 17 '05 #32
Stephen

I was asking about this:

"Essentially string variables in VB (post VB3) are what is called a
basic
string (BSTR). The variable actually contains a pointer to a memory
location where the data for the string is held, this string is null
terminated. The four bytes just before the memory location pointed to,
holds data which tells us how big the block of memory used to hold the
string is. So, in the extract from Bruce McKinney, when he talks about
the
empty BSTR and he refers to the single null character to the right of
the
address he is talking about the Null character which terminates the
empty
string, when he talks about the long integer containing zero he is
talking
about the memory location which tells us how long the string is (i.e.
it has
zero length).

If we look in the MSDN we get confirmation that this is the case. Now
I'm
using the MSDN from October 2001 so I can't give
online references, but in the article "Strings the OLE Way" by Bruce
McKinney April 18, 1996 we read:-

"Rule 8: A null pointer is the same as an empty string to a BSTR.
Experienced C++ programmers will find this concept startling because it
certainly isn't true of normal C++ strings. An empty BSTR is a pointer
to a
zero-length string. It has a single null character to the right of the
address being pointed to, and a long integer containing zero to the
left. A
null BSTR is a null pointer pointing to nothing. There can't be any
characters to the right of nothing, and there can't be any length to
the
left of nothing. Nevertheless, a null pointer is considered to have a
length
of zero ..."
"
And my question is about "" which is or has a varptr, say x. x points
to the strptr of "", say y. At y - 4 we find 4 bytes which show the
length of "", so we find 4 bytes that represent zero.
I have always assumed we would find zip at y. If I am interpreting
Terry and his quotes correctly, the accept interpretation is that we
find a null character at y.

I am asking, what would we find at y if there were not a null character
at y, that is if "" were fully represented by the zero at y-4, and the
contents of y were irrelevant.

Dec 17 '05 #33
This has brought me to another issue about Access 2003 and Intel
Centrino.
In almost any kind of testing, almost always the first test loses and
the last test wins.
--------------------
This sequence:

vbNullString
UnitializedString
""

shows "" is faster than vbNullString.
---------------------------------------------------

----------------------------
This sequence

""
UnitializedString
vbNullString

shows vbNullString is faster than "".
----------------------------------------------------

I know that caching may have an effect here.But, although I can't test
it, my recollection that it never had such a marked effect prior to
Access 2003.

To try to assess things correctly I have built into my tests an extra
sequence that is not timed which you can see in the code below. When I
run that I get about what Terry gets for concatenation.
There is no appreciable difference between vbNullString and "". An
unitilalized string is minimally slower, but not enough that one is
likely to notice.

Finally, my first response to some assertations about vbNuullString was
about, "vbNullString is likely to be faster because memory is
pre-assigned for it".
I think "vbNullString is likely to be faster because no memory is
assigned for it is likely to more accurate". Whether it's likely or
not, in some cases, including the OP's case. it seems that is not.

But there are other valid reasons for using vbNullstring.

After reading all the thread again, I'll retract my vbNullString is not
a real string statement and replace it with vbNullString is a special
string and works is special ways.

That code ...

Option Explicit

Private Declare Function GetTickCount Lib "kernel32" () As Long
Private Const iterations As Long = 1000000
Sub temp()
Dim q As String
Dim r As String
Dim s As String
Dim t As Long
Dim u As Long
r = " P "

' ----------------

For u = 1 To iterations
q = r & vbNullString
Next u

Debug.Print "--------"
t = GetTickCount
For u = 1 To iterations
q = r & vbNullString
Next u
Debug.Print "vbNullString " & GetTickCount - t

' ----------------

For u = 1 To iterations
q = r & s
Next u

t = GetTickCount
For u = 1 To iterations
q = r & s
Next u
Debug.Print "unitialized string " & GetTickCount - t

' ----------------

For u = 1 To iterations
q = r & ""
Next u

t = GetTickCount
For u = 1 To iterations
q = r & ""
Next u
Debug.Print "literal " & Chr(34) & Chr(34) & " " & GetTickCount - t
Debug.Print "----------------"

End Sub

Dec 17 '05 #34
At y we find the block of memory which holds the string this is then
terminated by a null character (a pair of bytes holding 00)

With an empty string the y-4 to y-1 memory holds 00 00, indicating the that
the string has zero length, therefore when we look at y we find no data
terminated with a pair of byte holding 00.

We can modify some code I posted earlier to get what is in memory from y-4
right through to the terminating character

Option Explicit

Private Declare Sub CopyMemory _
Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)

Sub TestString3()
Dim b As String
Dim c() As Byte
Dim lngSize As Long
Dim lngStrLocn As Long
Dim lngSizeLocn As Long
Dim intCount As Integer

b = "a"

lngStrLocn = StrPtr(b)

lngSizeLocn = lngStrLocn - 4

Call CopyMemory(lngSize, ByVal lngSizeLocn, 4)

ReDim c(1 To lngSize + 6)

Call CopyMemory(c(1), ByVal lngSizeLocn, lngSize + 6)

Debug.Print "Variable b = '" & b & "'"
Debug.Print "================="
Debug.Print "String", "Size", "String"
Debug.Print "Location", "Location", "Length"
Debug.Print "---------", "---------", "-------"
Debug.Print lngStrLocn, lngSizeLocn, lngSize
For intCount = 1 To lngSize + 6
Debug.Print "y" & intCount - 5 & " ="; c(intCount)
Next

b = ""

lngStrLocn = StrPtr(b)

lngSizeLocn = lngStrLocn - 4

Call CopyMemory(lngSize, ByVal lngSizeLocn, 4)

ReDim c(1 To lngSize + 6)

Call CopyMemory(c(1), ByVal lngSizeLocn, lngSize + 6)

Debug.Print
Debug.Print "Variable b = '" & b & "'"
Debug.Print "================="
Debug.Print "String", "Size", "String"
Debug.Print "Location", "Location", "Length"
Debug.Print "---------", "---------", "-------"
Debug.Print lngStrLocn, lngSizeLocn, lngSize

For intCount = 1 To lngSize + 6
Debug.Print "y" & intCount - 5 & " ="; c(intCount)
Next
End Sub

This returns
Variable b = 'a'
=================
String Size String
Location Location Length
--------- --------- -------
2247068 2247064 2
y-4 = 2
y-3 = 0
y-2 = 0
y-1 = 0
y0 = 97
y1 = 0
y2 = 0
y3 = 0

Variable b = ''
=================
String Size String
Location Location Length
--------- --------- -------
2422604 2422600 0
y-4 = 0
y-3 = 0
y-2 = 0
y-1 = 0
y0 = 0
y1 = 0

From the results we can see that for an empty string
1) the total of y-4 to y-1 is 0
2) that at y(0) we have just the two terminating bytes (which are set to
0 in both cases)

With the string containing the letter 'a' we can see that
1) the total for y-4 to y-1 is 2 (that is the string occupies 2 bytes of
memory)
2) in the 2 bytes of memory occupied by the string there is a 97 0 (97
is the ascii for a)
3) there are 2 terminating bytes both containing a 0

The following from "Chapter 6: Strings" from "Win32 API Programming with
Visual Basic" by Steven Roman may help:=

" ...
There are several important things to note about the BSTR data type.

The BSTR is the actual pointer variable. It has size 32 bits, like all
pointers, and points to a Unicode character array. Thus, a Unicode character
array and a BSTR are not the same thing. It is correct to refer to a BSTR as
a string (or VB string) but, unfortunately, the Unicode character array is
also often called a string! Hence, we will not refer to a BSTR simply as a
string--we will refer to it by its unequivocal name--BSTR.

The Unicode character array that is pointed to by a BSTR must be preceded by
a 4-byte length field and terminated by a single null 2-byte character (ANSI
= 0).

There may be additional null characters anywhere within the Unicode
character array, so we cannot rely on a null character to signal the end of
the character array. This is why the length field is vital.

Again, the pointer points to the beginning of the character array, not to
the 4-byte length field that precedes the array. As we will see, this is
critical to interpreting a BSTR as a VC++-style string.

The length field contains the number of bytes (not the number of characters)
in the character array, excluding the terminating null bytes. Since the
array is Unicode, the character count is one-half the byte count.
.... "

--
Terry Kreft

"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
Stephen

I was asking about this:

"Essentially string variables in VB (post VB3) are what is called a
basic
string (BSTR). The variable actually contains a pointer to a memory
location where the data for the string is held, this string is null
terminated. The four bytes just before the memory location pointed to,
holds data which tells us how big the block of memory used to hold the
string is. So, in the extract from Bruce McKinney, when he talks about
the
empty BSTR and he refers to the single null character to the right of
the
address he is talking about the Null character which terminates the
empty
string, when he talks about the long integer containing zero he is
talking
about the memory location which tells us how long the string is (i.e.
it has
zero length).

If we look in the MSDN we get confirmation that this is the case. Now
I'm
using the MSDN from October 2001 so I can't give
online references, but in the article "Strings the OLE Way" by Bruce
McKinney April 18, 1996 we read:-

"Rule 8: A null pointer is the same as an empty string to a BSTR.
Experienced C++ programmers will find this concept startling because it
certainly isn't true of normal C++ strings. An empty BSTR is a pointer
to a
zero-length string. It has a single null character to the right of the
address being pointed to, and a long integer containing zero to the
left. A
null BSTR is a null pointer pointing to nothing. There can't be any
characters to the right of nothing, and there can't be any length to
the
left of nothing. Nevertheless, a null pointer is considered to have a
length
of zero ..."
"
And my question is about "" which is or has a varptr, say x. x points
to the strptr of "", say y. At y - 4 we find 4 bytes which show the
length of "", so we find 4 bytes that represent zero.
I have always assumed we would find zip at y. If I am interpreting
Terry and his quotes correctly, the accept interpretation is that we
find a null character at y.

I am asking, what would we find at y if there were not a null character
at y, that is if "" were fully represented by the zero at y-4, and the
contents of y were irrelevant.

Dec 17 '05 #35
I understand everything now. It can all be summarized with

vbNullString = vbNullChar / 2

or

(a null string is half a null char)!

so the length of a null string must be half the length of a null char

which proves that 0 = 2/2

or

0 = 1

Right?

:-)

Dec 17 '05 #36
Exactly !

<g>

--
Terry Kreft

"Lyle Fairfield" <ly***********@aim.com> wrote in message
news:11**********************@z14g2000cwz.googlegr oups.com...
I understand everything now. It can all be summarized with

vbNullString = vbNullChar / 2

or

(a null string is half a null char)!

so the length of a null string must be half the length of a null char

which proves that 0 = 2/2

or

0 = 1

Right?

:-)

Dec 17 '05 #37
"Terry Kreft" <te*********@mps.co.uk> wrote in
news:Vx********************@karoo.co.uk:
I think there is a word missing. I'm taking it that what you
meant to write was:-
Would you say there is no reason to prefer it to "" in pure
VBA loops?
--
If you are saying do I believe there is a performance advantage to
assigning vbNullString to a string variable in a loop rather than
assigning "" then I would say there alsmost certainly is.

If you assign "" to a string variable then we know that 6 bytes of
memory is having to be written every time, together with all the
system resources that such an assignment implies. Assigning
vbNullstring means that all that should need happen is at worst a
release of memory, which really should be more efficient than
assignment.
This could, of course, be ameliorated by assigning the "" to a
constant outside the loop, but then you're just replicating an
existing constant, while actually using more memory to do it. The
amount of memory is quite insignificant in that case, of course, but
logically, it's doing more work than you need to do.
There is the factor that 6 bytes of memory is being used, which is
unnecessary, but I would have thought this to be trivial unless of
course a large number strings are being used.
But if you're doing something like:

strVariable = rs!Field & ""

on each row of a large recordset, are you not using that 6 bytes
with every single row?
Woukd the user notice a performance increase using vbNullString?
I doubt it.

Caveat, the above response is pure speculation.


Well, I'd think that if you're concatenating with "" inside a loop
with thousands or 10s of thousands of repetitions, it *could* make a
difference, but I'd expect that with a recordset, there are much
more CPU-hungry operations going on than the cost of allocating that
6 bytes over and over again.

No?

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Dec 17 '05 #38
"Stephen Lebans"
<ForEmailGotoMy.WebSite.-WWWdotlebansdot...@linvalid.com> wrote in
news:np**********************@ursa-nb00s0.nbnet.nb.ca:
Lyle I believe Terry stated that a difference would be noticeable
in assigning a variable to vbNullString over "".


This was also my original statement of the problem.

Seems to me that Lyle has spent a lot of time trying to disprove
something that was never at issue.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Dec 17 '05 #39
rkc <rk*@rochester.yabba.dabba.do.rr.bomb> wrote in
news:gI*******************@twister.nyroc.rr.com:
Stephen Lebans wrote:
Lyle I believe Terry stated that a difference would be noticeable
in assigning a variable to vbNullString over "". Since a string
Var not initialized is the same as vbNullString:


The original claim by dwf was concatenating a string (or Null as
in the case of a control with no value) with VbNullString is
faster. There is essentially no difference in that case.


Faster than concatenating with "" *not* stored in a variable.

This is precisely what Terry has demonstrated is true.

Lyle has been off on a tangent since almost the beginning, casting
the issue as something entirely different than the original context.

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Dec 17 '05 #40
"Terry Kreft" <te*********@mps.co.uk> wrote in
news:1K********************@karoo.co.uk:
Summary
=======
Whenever we concatenate a string the memory location of the data
changes.

When we assign an initialised string the meory location changes.

When we assign a Null string the memory location doesn't change
(because it's null).


Does this not, therefore, demonstrate that my original point (which
is really just something I got from MichKa) is, in fact, correct?

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/
Dec 17 '05 #41

David W. Fenton wrote:
Lyle I believe Terry stated that a difference would be noticeable
in assigning a variable to vbNullString over "".


This was also my original statement of the problem.

Seems to me that Lyle has spent a lot of time trying to disprove
something that was never at issue.


Sorry, I must have missed your original statement of the problem;
perhaps it has been expunged from usenet. Silly me, I thought your
original statement of the problem was in

http://groups.google.ca/group/comp.d...9c0cd11672ed4f

where you stated:

"And I believe it's always best to use vbNullString in place of an
empty string."

Dec 17 '05 #42
I would think your first poiint about the constant is spot on.

strVariable = rs!Field & ""
===================
I would expect from what we now know that this would involve.
Create memory space for the "" variable (6 bytes)
Create pointer to the "" variable
Create memory space for strVariable
Create pointer for strVariable
Assign value to strVariable

or sometihng like that.

The interesting thing, which I guess you're getting at is when does the ""
variable get destroyed. If the variable id detroyed as soon as we leave the
line (which seems the sensible thing to do) then there is never more than a
spurious 6 bytes of memory being wasted if it isn't then we could see a
serious memory usage over a large recordset.

The following code doesn't exactly match your example but I think it
probably illustrates what is happening

Private Declare Sub CopyMemory _
Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
ByRef Destination As Any, _
ByRef Source As Any, _
ByVal Length As Long _
)

Sub TestString4()
Dim b As String
Dim c() As Byte
Dim lngVarLocn As Long
Dim lngVarContents As Long
Dim intCount As Integer

b = ""
lngVarLocn = VarPtr(b)
Call CopyMemory(lngVarContents, ByVal lngVarLocn, 4)
' This proves we are getting the contents of the
' memory address at lngVarLocn by using copymemory
Debug.Print lngVarContents, lngVarLocn, StrPtr(b)

For intCount = 1 To 4
lngVarLocn = VarPtr("")
Call CopyMemory(lngVarContents, ByVal lngVarLocn, 4)
Debug.Print lngVarContents, lngVarLocn
Next
End Sub

The results I get from this are as follows

2318012 1308396 2318012
0 1308368
0 1308368
0 1308368
0 1308368

The results seem to show that the memory location which held the "" is
pointing to nowhere on the following line, therefore I think we can conclude
that the "" variable is cleaned up.

Concatenating in loop
=================
I would agree with what you say here.


--
Terry Kreft

"David W. Fenton" <XX*******@dfenton.com.invalid> wrote in message
news:Xn**********************************@127.0.0. 1...
"Terry Kreft" <te*********@mps.co.uk> wrote in
news:Vx********************@karoo.co.uk:
I think there is a word missing. I'm taking it that what you
meant to write was:-
Would you say there is no reason to prefer it to "" in pure
VBA loops?
--
If you are saying do I believe there is a performance advantage to
assigning vbNullString to a string variable in a loop rather than
assigning "" then I would say there alsmost certainly is.

If you assign "" to a string variable then we know that 6 bytes of
memory is having to be written every time, together with all the
system resources that such an assignment implies. Assigning
vbNullstring means that all that should need happen is at worst a
release of memory, which really should be more efficient than
assignment.


This could, of course, be ameliorated by assigning the "" to a
constant outside the loop, but then you're just replicating an
existing constant, while actually using more memory to do it. The
amount of memory is quite insignificant in that case, of course, but
logically, it's doing more work than you need to do.
There is the factor that 6 bytes of memory is being used, which is
unnecessary, but I would have thought this to be trivial unless of
course a large number strings are being used.


But if you're doing something like:

strVariable = rs!Field & ""

on each row of a large recordset, are you not using that 6 bytes
with every single row?
Woukd the user notice a performance increase using vbNullString?
I doubt it.

Caveat, the above response is pure speculation.


Well, I'd think that if you're concatenating with "" inside a loop
with thousands or 10s of thousands of repetitions, it *could* make a
difference, but I'd expect that with a recordset, there are much
more CPU-hungry operations going on than the cost of allocating that
6 bytes over and over again.

No?

--
David W. Fenton http://www.dfenton.com/
usenet at dfenton dot com http://www.dfenton.com/DFA/

Dec 18 '05 #43
I ran the code as is and, later, substituting vbNullString for "", and,
later still, "fred" for "", and even later, an unitilaized string for
"".

And I changed the lest debug.print to be the same as the first.
[Debug.Print lngVarContents, lngVarLocn, StrPtr(b)]

And I changed the b to b(4) so that I could see better what was
happending with that.

The results made me suspect that VBA cleans up all string variables
(including vbNullString) on first reference such that subsequent
references point somewhere other than to their varptr, some sort of
short circuited strptr.

If this is the case, then vbNullString's advantage can only be its
readibility.

I think there is lots to think about in these results, especially the
significance of the (seeming) fact that b(0), b(1), b(2), b(3) after
first use, all (supposedly) point to 1308228 while having different
values.

var = ""
2193724 1716656 2193724
0 1308228 2193724
0 1308228 2193724
0 1308228 2193724
0 1308228 2193724
var = vbNullString
0 1716660 0
0 1308228 0
0 1308228 0
0 1308228 0
0 1308228 0
var = "fred"
149326236 1716664 149326236
0 1308228 149326236
0 1308228 149326236
0 1308228 149326236
0 1308228 149326236
var = "strUnitializedString"
0 1716668 0
0 1308228 0
0 1308228 0
0 1308228 0
0 1308228 0

Maybe it's time to let this thread dry up.

Dec 18 '05 #44

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Phil B Brubaker | last post by:
Need a routine no longer in User32.dll must get it from vb4's User.exe. How to 'import' this vb4 file into vb6? ExitWindowsExec is the routine in need. Ideas how to obtain it? Thanks, Phil
2
by: Raymond H. | last post by:
Hello, How to create a new sub-menu in projet vb4 when there is already no menu at all? I know this: Private Sub Command1_Click() For Rép = 1 To 5 Load MenuFich(Rép) Next Rép End Sub
2
VB4
by: Shard | last post by:
I have been offered Visual Basic 4 professional plus three programming books for next to nothing. As this is an older version of VB, I was wondering if it is worth my while to learn this version?...
1
by: R_O_O_K | last post by:
Hi! I have created a simple COM class in VC# (ie "Hello World" through Windows.Forms.MessageBox). When I try to use it in VB4 I get an error saying that the server CLSID {GUID...} can not be...
23
by: Carter Smith | last post by:
http://www.icarusindie.com/Literature/ebooks/ Rather than advocating wasting money on expensive books for beginners, here's my collection of ebooks that have been made freely available on-line...
34
by: John Harrison | last post by:
An odd confession; an odd request; but here's the tale.... My company has a few PC systems which we have used for about 7 years and not updated - we've "made do", and besides, "if it ain't...
1
by: Amjad | last post by:
Hi, I have an API (DLL) file that was developed in VB4 or VB5, and I have its old poor documentation (before the .NET era). I'm unable to import and use this old DLL file in the VB.NET! I...
1
by: Shogun | last post by:
I'm having problems with compatibility between VB4 and Office XP. VB4 only recognize Access 97 or below format, so I can't work with database files I create with my Office XP. Even if I convert the...
1
by: Buzzard | last post by:
Hi y'all, I had a windows 95 OSR2 computer that had VB4 on it, and it ran fine; but when I try to run VB4 under windows 98, I get that cryptic error message. I found a microsoft supposed fix...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.