Confused with VBA and VB variable addresses and pointers.

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

Confused with VBA and VB variable addresses and pointers.

Post by DocAElstein »

Hi
I have been going around in circles on this one for a few days, and I am still not sure if I have quite got it right.
Can someone help put me out of my misery by confirming some things or otherwise….

First, I think I do understand approximately how a VBA Long type variable and a VBA String type variable are handled in memory, and I think I understand the important differences in those two, ( and why) , in the way they are handled and stored. My confusion is related to exactly which memory addresses are being referred to in the following coding examples

Long example

Code: Select all

Sub ConfusedWithVBALongTypeMemoryStuff()
1 Dim Lng As Long
2 Debug.Print VarPtr(Lng)        '  2355700    I don't know where this number is held in memory. I don't care
3 Debug.Print VarPtr(ByVal Lng)  '  0
4 Debug.Print Lng                '  0
 
 Let Lng = 2

5 Debug.Print VarPtr(Lng)          '  2355700
6 Debug.Print VarPtr(ByVal Lng)    '  2

8 Debug.Print Lng                  '  2
End Sub 
In the first line of the coding above, Dim Lng As Long , Lng becomes a number which is made with 4 bytes, (32 bits). It is called a Pointer. The actual number refers to the first memory address ( the first memory address at the left hand side) of 4 Bytes (32 bits) set aside in memory to hold the final value which I later assign to the variable, (with Let Lng = 2 ). In other words, the act of doing Dim Lng As Long reserves for me 4 sequential memory addresses/ byte locations, in a sequential row as it were. And the first one, the first byte, at the left as it were, has the memory location got for me with the second code line, Debug.Print VarPtr(Lng) (by me , I got the value shown in the ' comment - 2355700** )
Q1: Have I got that right?

The third line, Debug.Print VarPtr(ByVal Lng) , is perhaps giving me the same as the 4th line, which is the value of the variable. For the case of a Long Type it does have a value even before I assign one. It has the value 0. If I assigned it 0 with Let Lng = 0 nothing would change anywhere
Q2: Have I got that right?

In line 5 , the memory location has not changed, as it never does for the VBA Long type, even if I assign a much different number. This is because It doesn’t need to change, because 32 bits are enough to hold in binary any number in the range of the defined number range for a VBA Long type
Q3: Have I got that right?

Line 6 aqnd line 8: My results suggest that Debug.Print VarPtr(ByVal Lng) and Debug.Print Lng are giving me the same thing – the value it sees at the address, 2355700**.
Q4: Any comments at all on that?
( **The address I got was 2355700 , you will get a similar but different number. I am OK with that and understand why that is )

This next bit is what has got me a bit confused. The 32 Bit number, the number returned from the second code line, Debug.Print VarPtr(Lng) , (by me 2355700** ) , is presumably held somewhere in memory as well? Where I don't know (I am not complaining, I just am trying to confirms that I got that right). I know the value held there, (by me 2355700** ) , but I don’t know where that number is being held
Q5: Have I got that right? (I expect VarPtr( ) knows that memory location as it goes there and gets the number in it for me. ( Maybe there is a "stack" of active variables and their values somewhere we ain't privy to?)

Q6: In this situation what is actually the "Pointer". Is it
_ the number the second code line, Debug.Print VarPtr(Lng) , gets me,
_ is it the variable Lng ,
_ is it the Bytes used for it somewhere I don't know?
Or is the word "pointer" some vague concept you would use to refer to one or more of those things or all of them depending on the context in which you use it


I have some similar questions on the VBA String type. It will perhaps help tidiness and later reference if I do another post for that…..


_.____________________________________________

Ref: VarPtr , StrPtr stuff https://classicvb.net/tips/varptr/ , https://www.vba-tutorial.de/referenz/zeiger.htm
https://www.excelfox.com/forum/showthre ... #post11886
Last edited by DocAElstein on 06 Jan 2025, 14:54, edited 2 times in total.
Regards , Ālan , DocÆlstein :england: , :germany:

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

Re: Confused with VBA and VB variable addresses and pointers.

Post by DocAElstein »

…….. continued, sort of, from last post


…. Confused with VBA and VB String Pointer Stuff

First, I do understand
_ (i) that String memory handling generally in computing, is a bit more dynamic/ complex than something like for a simple number, since even with modern computers, we don’t want to go around reserving a Giga Byte or two of memory every time we Declare a string variable.
and
_(ii) thanks to a lot of research and help from here, I am pretty well clued up now on all the various Ascii Ansi, Unicorns and other character encoding beasts roaming about ..

Once again my main confusion just now is/ was to do with what memory addresses / pointers are referring to what / where etc…

So, bearing that in mind…..
and with reference to the coding below….

After a month on and off researching VB String stuff, and VBA – VB win 32 API stuff, I was not too sure anymore that I even understood the very first line, Dim Str As String, … but as is often the case, preparing carefully the question can often help get the answer… The second code line Debug.Print VarPtr(Str) actually returned me the very same number as the second code line in the coding from the last post, Debug.Print VarPtr(Lng)!! I do realise that will not always be the case, but as I ran the coding shortly after running the previous coding on the same computer, then there is a chance it will be the same, as it was, … because….. how about this: What Dim Str As String in the coding below is doing, is very similar to what the Dim Lng As Long did/does in the coduing from the last post, - it sets aside once again 4 Bytes (32 bits) for me. But the difference being now is that it is not reserving me a place to store any final number or character values, rather it is reserving me a place … for …. a 32Bit Pointer , specifically a pointer to a VB String, (what I might refer to as a COM BSTR), and if I am feeling very adventurous I might say it’s a LPWSTR pointer, (or variation of) , which means that when it eventually gets filled in, it will be the address not of the start memory point I finally use for my string, but rather 4 Bytes along where the actual Unicode UTF-16 LE encoding Bytes start.
Q7. Have I got that right?

So I could say, what I have is a VBA Pointer to a VB Pointer, or perhaps a VBA Pointer to what likely will be a VB Pointer – depending on how you feel the word pointer should be used
Q8. Have I got that right?

The result 0 of code line 3 and code lines 4 are, I think, telling me the bit I think I know, -they are telling me that, unlike in the case of the Long I have not yet reserved any memory for my final character string.
Q9a) Have I got that right?

Q9b) This is a tricky one that might get me hate mail. I am sure many people would tell me that at this point ( I mean at the point before Let Str = "ABCD" ) my Str variable is a vbNullString. I don’t see that. I think I have nothing to do with a VB string at this point? All I have is an empty VBA 32 bit pointer, (or maybe better said just a 4 Byte, 32Bit chunk of memory reserved) and possibly even that chunk of memory is indistinguishable from a Long variable of value 0
Any comments on that?

Q9c) I am not too clear what the difference is in these 2(3) code lines.
VarPtr(ByVal Str)
StrPtr(ByVal Str) ; StrPtr(Str)

It is discussed at the first of the references below, but I cannot quite understand what they are on about. Apparently the StrPtr( ) was introduced to make sure you go to the actual Unicode UTF-16 LE encoding Bytes start bit. (the 5th byte along ). But VarPtr(ByVal Str) seems to be doing this. Is this maybe VBA being a bit cleverer with the VarPtr( ) than VB is / was?

Q10 This is similar to Q5. The 32 bit address value/ number of the variable Str (by me 2355700** ) , is itself somewhere in memory. I don’t know where, that is to say I do not know the memory location holding that number . I don't particularly care about not knowing where it is. I am just wanting that fact confirmed.
Is that correct?

I think the rest of the coding makes sense to me. The VBA Pointer address generally does not change, (code line 5), the other 2(3) code lines 6 and 7 all do the same thing ( differences in what / how is Q9c). Although the 3 values are always the same value, that value will likely change every time you run the coding. I am OK with understanding what is going on there

( As for code line 8, that, and related VB API stuff, is the subject of another Thread I want to get back to, but I got a bit stuck on the issues I raised in this Thread, so later on that one. - Just passing interest, a taste of interesting things to come as it were, …. what we have in code line 8 is VBA knowing what's going on. VBA does a lot of heavy stuff for us. VB win 32 APIs, used in VBA, on the other hand, can get a bit confused, … the poor old things can even get confused with VB strings more than half the time…. But we will soon have all that sorted as well, :) , :wink: :grin: :cool: )

String example coding

Code: Select all

Sub ConfusedWithVBAandVBStringPointerStuff()
1 Dim Str As String
2 Debug.Print VarPtr(Str)        '  2355700   I don't know where this number is held in memory. I don't care
3 Debug.Print VarPtr(ByVal Str)              ' 0
4 Debug.Print StrPtr(ByVal Str); StrPtr(Str) ' 0   0

 Let Str = "ABCD"
5 Debug.Print VarPtr(Str)                                      '  2355700 - makes sense - no reason for this address to change. It is the first Byte of the 4 bytes that holds the VB pointer/ address, whatever value that is
6 Debug.Print VarPtr(ByVal Str)               '  4028444
7 Debug.Print StrPtr(ByVal Str); StrPtr(Str)  '  4028444  4028444

8 Debug.Print Str
End Sub 
Q 11. Is the following beautiful sketch an accurate technical depiction of the situation just before the above coding ends?
In that sketch I have enclosed 3 memory chunks, and I have, sort of , connected them with arrow/pointers:
, starting form the bottom there are two memory chunks of 4 Bytes.
The bottom I know what is in it but not where it is.
The middle one I know where it is and what is in it
The top enclosed memory chunk in this example is 14 bytes, ( it would be 18 Bytes if I had ABCDEF, and so on ).


https://i.postimg.cc/L6zbgmFC/A-VBA-Uni ... y-name.jpg
A VBA Unicorn . a beast by any name.JPG

Thanks for any help, comments , confirmations etc
Alan

Ref: VarPtr , StrPtr stuff
https://classicvb.net/tips/varptr/
https://www.vba-tutorial.de/referenz/zeiger.htm
You do not have the required permissions to view the files attached to this post.
Regards , Ālan , DocÆlstein :england: , :germany:

User avatar
SpeakEasy
5StarLounger
Posts: 722
Joined: 27 Jun 2021, 10:46

Re: Confused with VBA and VB variable addresses and pointers.

Post by SpeakEasy »

>In the first line of the coding above, Dim Lng As Long , Lng becomes a number which is made with 4 bytes ...
... and initialises it to 0
VB6 Documentation
... a numeric* variable is initialized to 0, a variable-length string is initialized to a zero-length string (""), and a fixed-length string is filled with zeros. Variant variables are initialized to Empty. Each element of a user-defined type variable is initialized as if it were a separate variable.
*Booleans are considered numeric

Ok, next:

>Debug.Print VarPtr(Lng)
>Debug.Print VarPtr(ByVal Lng)

Here you need to get a better understanding of what actually happens when we call a procedure. A simplified version soi that the parameters are pushed on to the stack by the call, and pulled off the stack in the procedure. ByRef and ByVal define HOW those parameters are passed on the stack. ByRef means a copy of the pointer is put on the stack. ByVal means the pointer is dereferenced and the actual value it points to is put on the stack

And all VarPtr really does is pop the value that has been placed on the stack and return it.

>Debug.Print VarPtr(Lng)
therefore returns the value of the pointer, whilst
>Debug.Print VarPtr(ByVal Lng)
returns the value the pointer pointed to.

(However!!! This byval 'trick' only works if the value pushed on to the stack meets the internal function prototype (in other words, if what you attempt to push onto the stack is not a 4-byte value then you'll get a bad calling convention error or (if fewer than 4 bytes) an unexpected value.)

>32 bits are enough to hold in binary any number in the range of the defined number range for a VBA Long type
Q3: Have I got that right?

By definition a VBA Long is 32bits, So ... yes. But that's not why the memory location has not changed. I am not going to get into the Common Object File Format (COFF) and symbol tables here, but that provides you some nice new keywords to Google ... (but be warned, you are moving very much away from VBA here). This, by the way, is essentially the "... 'stack' of active variables and their values somewhere we ain't privy to?"

>_ the number the second code line, Debug.Print VarPtr(Lng) , gets me,
>_ is it the variable Lng

Lng is the symbol for the pointer,
VarPtr(Lng) gets you the value of the pointer, which is the memory address the pointer is pointing to
Lng itself is stored in the COFF symbol table

Note that one of the whole points of high-level languages is to (try to) hide this stuff away from you.

As for your diagram concerning strings ...

I'd call Str a VB(A) string pointer which in turn points to a BSTR (which you technically wouldn't call a BSTR pointer; a BSTR IS a pointer, it certainly is not a VBA pointer of any sort. Nor is it an LPWSTR (or the other types your diagram mentions) except in the limited sense that the data string pointed to cannot contain nulls when used by VB(A), and thus technically meets the definition of LPWSTR

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

Re: Confused with VBA and VB variable addresses and pointers.

Post by DocAElstein »

Thanks for the reply, its very helpful as ever to stop my train of thoughts derailing too badly

_> The VB6 Documentation :- Interesting that you quote some VB6 documentation. …. numeric* variable is initialized to 0, a variable-length string is initialized to a zero-length string (""),
, because I decided a week or so ago to add installing VB, on my list of things to do, probably starting with VB6, as I want to check some of my recent research in Visual Basic. (It will be a while though before I do that. Maybe it will happen somehow when I dig out and dust down all the VB books I collected 10 years ago. I was going to use them as decoration, but maybe a disc will fall out of one of them, and I won’t be able to resist the temptation to slip it in a laptop and see what happens. But I have not given it any serious thought though yet.)
I may let that ... and initialises it….. stuff hang a bit. Because, there are some issues there I might rather prefer to cross check when I have VB6 up and running:
_ The number does not sound too bad, but
_ zero-length string "" versus vbNulllString sets alarm bells off in my head as maybe it can be a can of worms complicated by the extra pointer issue in VBA with a VB(A) Pointer to a VB Pointer (aka VB(A) Pointer to a BSTR)
If I start telling people that Dim Str As String …. Initializes to a zero-length string "" , then I will be in trouble for sure, because in VBA I don't think it does. I am not sure about VB

I want to leave that until I can do some cross checks on VB ( VB6) with a few of my recent VB String research and development stuff…. unless someone else knows for sure and can explain it clearly
_.______________-

Q1 Q5 Q10 The first bottom memory place/chunk, ( Long or String ) ….. I said… I know what is in it, but not ( yet ) where it is held / what it is held in .
I may have been not so off. So I was right in thinking we have that first memory usage. It is in that COFF thing

I won’t google or research that COFF thing just yet. I have pencilled that in for after I have made some more good progress on my eternal life project, other wise it could be deadly if I start looking at that now, as I estimate I need 10-20 years to understand any of that.
It is very helpful to know about it, as I can think of some temporary representation of it , for now, so that I can move on.
I do have some initial interesting ideas and lateral thought on a way to sketch that. I will have some stack of norm size Pallets in some sort of Shelf / Table/ trendy furniture arrangement, from bottom left in the sketch extending upwards. I have added a Buffer to fill in for later reference. I certainly won’t get on with that project until after the snow melts, then some time in the future me and my team can construct some models when I am drinking and grilling at my disused railway hideout
Maybe my instinct / gut feel was not so bad either. I did put 4 legs on that bottom chunk of memory so that goes a bit in the direction of a Table or stack. Or maybe not if the COFF is involved with more than the bottom memory chunk***

If I understand correctly, I can say that the memory address of the bottom memory chunks in the following two diagrams are not so easy to get , (- they are easy to get for the others ( second and final for the long, and the middle and top for the string) )
I don’t particularly need to know them bottom memory chunk location, so for now I am OK with saying they are on / in the COFF table stack. For the time being I am happy to leave it at that
(*** I am hoping that the COFF thing is only concerned with the bottom chunks of memory from my sketches. If it isn't then I think I would best forget completely about it until I have finished securing eternal life. I say this because something like a number variable might "fit on it" easily , but organising a string in it would be messy I expect , you inferred that the COFF - stack has a 4 byte size convention? - or maybe you didn't, I may have misunderstood. Perhaps it’s the ByVal 'trick' in VarPtr( ) that only works on something of 4 Bytes? )

_._______________
SpeakEasy wrote:
06 Jan 2025, 16:40
..Here you need to get a better understanding of what actually happens when we call a procedure.
I think I may have a reasonably understanding of the ByVal ByRef stack stuff within VB / VBA, but what you wrote is helpful on keeping me on track on the ByVal ByRef stuff:
I actually started this Thread as I had got a bit stuck on a page of musings on an extended explanation of the conventional ByVal ByRef in procedure calls in VBA , which I started a few days ago.
I am basically taking the typical explanation of what is going on with ByVal ByRef issues when we call a procedure and trying to extend it to include more detailed variable pointer issues.
( I started those musings as I want to get clear exactly what is going on in VB / VBA before I go back to that other win API Thread, - the one that set me off reading all up to and including Chapter 6 of that VB book, which I have done thoroughly now…
The point is, I think, all this we is discussing here just now is within VB / VBA, and an important point I think for me to understand is that all these ByVal and ByRef are instruction to VB / VBA?
I think also that in VBA coding where win 32 API stuff is involved, any ByVal ByRef are also still instructions to VBA? The other win 32 API dll stuff that I may set off in a VBA coding, goes off doing something in some C language I believe, where memory management is different and pointers perhaps play a more important role. (I expect it ( C language ) don't have a clue how we are messing with our stacks of stuff and I have a gut feeling (from a lot of stuff I read recently that I don't really understand) that reserving memory space and the such for us in VB / VBA is a hobby it ( it being C language) has not much interest in. C language does not really know what we are up to. A running API dll is not really in VB / VBA runtime. It can't get at our stacks in the same way that our non external called functions and procedures can. This is why, I believe, that we often organise a buffer string variable for the API to return us a string in. A win API that we set off, does not know what we are up to, so it is not a good idea for them to try and organise our memory reservations management. It might cause some nasty low level problems with memory being eaten up mysteriously – but this is all my usual uneducated guess)

_.___________

..cont in next post
Last edited by DocAElstein on 08 Jan 2025, 12:12, edited 2 times in total.
Regards , Ālan , DocÆlstein :england: , :germany:

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

Re: Confused with VBA and VB variable addresses and pointers.

Post by DocAElstein »

… cont from last post

I was not quite sure initially what to make of the VarPtr( ) ,- for a while I was thinking (wrongly I now think) that it was an external function like a win 32 API thing. I was thinking that because
_ Overriding the default ByRef with a ByVal at the call line is a typical characteristic of an external function, apparently.
_ I also noticed that As Any appearing, which I only recently came across, and I thought it was an API thingy something to do with an API not being too interested in a variable type sometimes , but rather often being interested in a pointer to it.
Now I am not so sure.
Who knows what / where this mystical undocumented hidden VarPtr( ) is coming from or doing…..
But I am going now more in the direction to think it’s a VB function not an external function like an API
I am still not clear of the difference with VarPtr(By Val ) and StrPtr(), but perhaps something will emerge if I frequently experiment with one or the other in further API experiments

Generical Mismomers….
_As for the BSTR / BSTR pointer, - yeh, I need to be a bit more careful with the exact definitions of these things. ( We probably all need to , - it seems to be a Human characteristic of all of us that no matter how clear and precise we get these terms sorted in our heads, we never the less all then go on to regress back later, usually not much later, into using these terms imprecisely or wrongly , just like in the ANSI & co generical mismomers)
_ LPWSTR ( or LPCWSTR or LPTSTR or LPCTSTR )
I also must stamp in my head that the LPWSTR is a Data Type , and not mix it up with the BSTR. My mix up comes from the fact that a BSTR might "fit" where one of these Data Types is required, ( although it is more complicated than that which is the main issue of that other win API Thread, ). These Data Types are the Types often appearing for the Types given as to be used in most newer documentation of the Windows API functions, that documentation being for C, not for VBA, ( but it’s not too difficult to convert them to a VBA win 32 API Declareation. )
That documentation using things like that for the types required is one thing making me think that API things are often interested in pointers rather than strings, and somewhere hidden in all this confusion is the in depth knowledge needed to know how to define and fill in correctly the parameters in win 32 API stuff. For example, I think if you really understand these things well, then it probably, in some cases, is clear that VBA coding saying ByVal in a win32 API Declareation can sometimes be doing something similar to what we might consider similar to a ByRef in a VBA procedure call
The LPWSTR, (or LPCWSTR or LPTSTR or LPCTSTR ) is the important one(s) for my various recent researching.
The following is easy enough to find in a few places, written more fully and formally, but just for future reference to remind me and jog my memory later, here is a description of the LPWSTR, in my words, as relevant for what I am doing and thinking about doing is … … If a parameter I need to give is described as a LPWSTR type, it means that I need to arrange in one way or another that it gets to, or is given directions by me somehow to, the start of the "2 Byte 16 Bit LE" bit of that top chunk of memory in my string diagram. Doing that so that things works as it should needs a reasonably good understanding of some things, and I am almost there.
This sketch is perhaps an acceptable generical pictorical depictation, to match my previous sketch attempts , here showing a Windows API LPWSTR string
Something I am not 100% clear on, is the main difference between MyAPIFunctionA and MyAPIFunctionW. In the literature its usually fogged off with a quick generical mismomical sentence like A is a ANSI version and W is a Unicode version. I am thinking they perhaps both appeared not so far apart historically and may in fact both have the same Unicode innards? Possibly the main difference is how they handle the string parameters that are given to them? Do you have any little insight Gem just to satisfy my slightly over average desire to know what’s going on in the innards?


It is easy to get all the definitions and things mixed up. Microsoft clearly often refer to a BSTR as a composite data type that consists of a length prefix, a data string, and a terminator, with no mention of it being a pointer, and the misuse of this term by Microsoft is something in that VB String book that is often criticised.
For the string example, I think the simplest description is
Str(VB(A) Pointer ) --->BSTR(VB Pointer)---->Final memory location of value in " 2 Byte 16 Bit LE, preceded by 4 Bytes giving the length, terminated in 0 (2 Byte 16 Bit LE 0 = 0 0 ) "
, But IMO something like that is useless at saying anything at all unless you already know it all, then it is perhaps useful to quickly jog the memory.


I tried to update my sketch idea, actually 2 of them now. I deliberately left the COFF table stack a bit vague and imprecise for now, for the sake of my health/ longevity. (Both sketches are depicting the situation just before the codings given previously end)
( I made the sketches myself :artist: :smile: )

Alan

https://i.postimg.cc/7hySGvsp/Skematic-VBA-Long.jpg https://i.postimg.cc/VLmjz8bt/Skematic-VBA-String.jpg
You do not have the required permissions to view the files attached to this post.
Last edited by DocAElstein on 08 Jan 2025, 12:47, edited 1 time in total.
Regards , Ālan , DocÆlstein :england: , :germany:

User avatar
HansV
Administrator
Posts: 79952
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Confused with VBA and VB variable addresses and pointers.

Post by HansV »

Dim s As String

does create a variable s that initially has value vbNullString = "" in VB6 and in VBA.

The zero-length string vbNullString is not to be confused with vbNullChar = Chr(0) (length=1).

I would avoid naming a variable Str. Although it is allowed, it may cause confusion since Str is also the name of a built-in function, see Str function.
Best wishes,
Hans

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

"" v vbNullString

Post by DocAElstein »

Thanks


...Hmm ... I thought "" and vbNullString were different ...... and that

Dim s As String

, create a variable s that initially has value vbNullString

An awfull lot of stuff on the internet says "" and vbNullString are different - first google hit I just got for example
https://stackoverflow.com/questions/324 ... 2#37796912
I know myself from a lot of recent API stuff that it can be important whether you use "" or vbNullString

Possibly I am missing the point again....

_.___________________________-

I never noticed that Str function before, thanks. I definately will avoid naming a variable Str from now on
Last edited by DocAElstein on 08 Jan 2025, 13:43, edited 1 time in total.
Regards , Ālan , DocÆlstein :england: , :germany:

User avatar
HansV
Administrator
Posts: 79952
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Confused with VBA and VB variable addresses and pointers.

Post by HansV »

I don't know about the technical implementation, that's not my thing. But try

Debug.Print vbNullString = ""
True

Debug.Print IsNull(vbNullString)
False
Best wishes,
Hans

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

"" v vbNullString

Post by DocAElstein »

I get the same results, but I am not too sure how to explain them.

_.__________________

This is one of the most typical things you see when people discuss these issues

Code: Select all

 Sub PointerZtr()
Dim Ztr As String
Debug.Print StrPtr(Ztr), VarPtr(ByVal Ztr)  '   0    0
 Let Ztr = ""
Debug.Print StrPtr(Ztr), VarPtr(ByVal Ztr)  '   143181340     143430148
 Let Ztr = vbNullString
Debug.Print StrPtr(Ztr), VarPtr(ByVal Ztr)  '   0    0
End Sub 
I do not know things like this well enough to explain that in great detail. Very approximately is that for the first and third set of results is that you have no memory reserved for a string, as you have no BSTR. You do have a VB(A) pointer, Ztr, so you have a memory reserve in the COFF for that, but it has a value 0
The middle set of results come as you have as on the other two, a reserved bit of memory in th COFF, but now also a memory reserve, for both the BSTR ( that has 143430148 in it) , and what I call the top ( third chunk of memor in my beautiful string pictorials )y, but this third memory chunk is missing the middle section, as in the following pictorial.
i may not have that 100% correct
Missing the middle Bit.JPG
You do not have the required permissions to view the files attached to this post.
Last edited by DocAElstein on 09 Jan 2025, 09:08, edited 1 time in total.
Regards , Ālan , DocÆlstein :england: , :germany:

User avatar
SpeakEasy
5StarLounger
Posts: 722
Joined: 27 Jun 2021, 10:46

Re: Confused with VBA and VB variable addresses and pointers.

Post by SpeakEasy »

> Interesting that you quote some VB6 documentation

It's also in the VBA documentation - https://learn.microsoft.com/en-us/offic ... -statement

>f I start telling people that Dim Str As String …. Initializes to a zero-length string "" , then I will be in trouble for sure, because in VBA I don't think it does. I am not sure about VB

Depends on your point of view. vbNullString is a special instance of an empty string (in both VBA and VB6). And, apart from Strptr (or tricks that do the same thing as strptr) there is no way to tell the difference between an assigned empty string and vbNullString, they behave in exactly the same way. vbNullString was a constant introduced in ..erm ... VB4 ... to allow passing null strings to API calls cleanly (basically it ensured that 0 was pushed onto the stack, without having to hack about with function prototypes and ByRef and ByVal)

One point of (perhaps minimal) interest is that

EmptyString=vbNullString

is faster (roughly 10x) than

EmptyString=""

This is true of all the predefined string and char constants, so

EOL =v bCRLF

is faster (roughly 5x) than

EOL = Chr$(13) & Chr$(10)

>Overriding the default ByRef with a ByVal at the call line is a typical characteristic of an external function

What?

>Who knows what / where this mystical undocumented hidden VarPtr( ) is coming from or doing…..

I was going to write something up, but then remembered Karl Peterson had done something on this some years ago, so: https://classicvb.net/tips/varptr/

>a quick generical mismomical sentence like A is a ANSI version and W is a Unicode version. I am thinking they perhaps both appeared not so far apart historically and may in fact both have the same Unicode innards?

I had a longer answer prepared, but have cut it down to a quote from MS documentation: Internally, the ANSI version translates the string to Unicode

>BSTR(VB Pointer)
A BSTR may be used by VB for strings but it is not a VB pointer. It comes from the world of COM.

User avatar
SpeakEasy
5StarLounger
Posts: 722
Joined: 27 Jun 2021, 10:46

Re: Confused with VBA and VB variable addresses and pointers.

Post by SpeakEasy »

>a reserved bit of memory in th COFF
I wouldn't get hung up on the COFF Symbol Table - you are starting to confuse yourself, and it really isn't important unless perhaps you are writing say a compiler

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

Re: Confused with VBA and VB variable addresses and pointers.

Post by DocAElstein »

Thanks for the extra vbBNullString info and similar performance stuff.
It is perhaps not too clear what that documentation is saying. It might be read as talking rubbish as Initialising is often defined as setting an initial value. So it could be interpreted as saying when I give it a value it is set to no value. So that is nonsense.
It could be interpreted as saying that when you do this,
Dim Ztr As String
Let
Ztr = ""

, you are initialising it, and because Ztr is a variable-length string, it is initialized to a zero-length string "" - I agree with that.
But I am saying that these two
Dim Ztr As String
Stop

, and
Dim Ztr As String
Let Ztr ="Anything"
Let Ztr =vbNullString
Stop

, end up both the same as each other but they are not a zero-length string. There are no strings, finally after either, rather just an empty pointer ( on the COFFee Table, maybe :coffeetime: )
I have not researched this one extensively, but a very quick Google shows smart people saying something similar to me , things like "" needs 6 Bytes, whereas vbNullString, needs no bytes ( needs no bytes on the top memory chunk - those smart people don't seem to understand yet about variable addresses and pointers and the COFFee Table ) . My explanation/ diagram ties up so far with what smart people are saying. But they are not the smartest. The smartest people are here, perhaps, me thinks
As you said it seems to be important for API stuff, which I have seen myself. Sometimes it definitely makes a difference if you use "" or vbNullString in API stuff
For now I will go with that ..... it is different, but that's open to interpretation. I think best when you say something you need to qualify it by saying in what context.
As you say, it is difficult to prove, since many things will see vbNullString and "" as the same, as you say, mostly they behave in exactly the same way .
Something like, they are not the same but behave the same mostly is the shortest answer perhaps
Or
They are pretty well the same for VBA but sometimes different in API stuff ……
This following also sounds quite nice, I will probably work that , or bits of it, into a few musings and give you the blame..
SpeakEasy wrote:
08 Jan 2025, 17:36
they behave in exactly the same way. vbNullString was a constant introduced in ..erm ... VB4 ... to allow passing null strings to API calls cleanly (basically it ensured that 0 was pushed onto the stack, without having to hack about with function prototypes and ByRef and ByVal)
_._________________________________
SpeakEasy wrote:
08 Jan 2025, 17:36
I had a longer answer prepared, but have cut it down to a quote from MS documentation: Internally, the ANSI version translates the string to Unicode
Intersting. That is the sort of little thing that helps things fall into place for me
_._____________________________
….. https://classicvb.net/tips/varptr/ ……
I have seen that Karl Peterson stuff, many times, (I referenced it a few times in posts above, and referenced it in my many recent musings elsewhere, as its where I got some of my musings info from). But I only understand a very small part of it. Or rather I understood nothing until I got better knowledgeable then went back and figured out a small amount of what he was saying. Most of it is either too advanced for me, and/ or you need perhaps a good knowledge of the earlier VB history. That may come when I dust down all those old VB books I got.
Here is the other reference I usually gave alongside, and in other places, https://www.vba-tutorial.de/referenz/zeiger.htm - As I recall I understood a bit more from that (The google translation on it is OK so it does not matter that it is in German)
_._____________________________
I am OK with not getting hung up on the COFF stuff. I had pretty well decided already to leave it for now. As you say, and confirmed as I thought, I don’t need it to move on for now. I will ask you again about it perhaps, in approximately 15 years time or so
_._________________________________
I am not so sure why you refer to the StrPtr( ) and similar as a trick. But then the point is that I do not understand it too much. It is a weird hidden beast https://i.postimg.cc/FKnRws23/Hidden-Mo ... -stuff.jpg
_._____________________
-----> >Overriding the default ByRef with a ByVal at the call line is a typical characteristic of an external function
What?
It is something I initially found by chance by experimenting over the last few eeks, but/ and then a few days later read in that Steven Roman book, Chapter 3, Page 35, we can override the default ByRef setting for an external function … by including the word ByVal in the function Call
So these two are the same

Code: Select all

Declare Function MyAPIFunction ……..  (ByVal  Ex As ….)
…..
….
Y = MyAPIFunction(Zed)

Code: Select all

Declare Function MyAPIFunction ……..  (ByRef Ex As ….)
…..
….
Y = MyAPIFunction(ByVal Zed)
So that's what made me think that VarPtr( ) & co, were maybe some strange external functions, because we can do VarPtr(ByVal ….. )
_.____________________________________________
SpeakEasy wrote:
06 Jan 2025, 16:40
... a BSTR (which you technically wouldn't call a BSTR pointer; a BSTR IS a pointer,
SpeakEasy wrote:
08 Jan 2025, 17:36
>BSTR(VB Pointer)
A BSTR may be used by VB for strings but it is not a VB pointer. It comes from the world of COM.
…. From one of my most recent pics…
This is a schematic of how VBA is holding the character string ABCD
, in its "2 Byte 16 Bit LE, preceded by 4 Bytes giving the length, terminated in 0 (2 Byte 16 Bit LE 0 = 0 0 )" (UTF-16-LE)
On second thoughts I might call this a COM "BSTR" or COM "VB String", which is what VBA uses to implement holding a string. (The terminology is often used imprecisely and inconstantly, with BSTR more correctly meaning the pointer variable, although BSTR is the general generical variable name
………………….
………………..
One might pictorially consider this arrow a VB Pointer ,……. But more correctly I might use that description to refer to the memory address 2355700 holding a number value 4028444…..or I might call BSTR the pointer


From Microsoft, just one example … A BSTR is a composite data type that consists of a length prefix, a data string, and a terminator

Take your Pick!, as the foreman jokingly said as he offered the new guy some shovels
Regards , Ālan , DocÆlstein :england: , :germany:

User avatar
SpeakEasy
5StarLounger
Posts: 722
Joined: 27 Jun 2021, 10:46

Re: Confused with VBA and VB variable addresses and pointers.

Post by SpeakEasy »

>"" needs 6 Bytes, whereas vbNullString, needs no bytes

Correct. But that's simply the low-level nitty gritty. From VB(A) programmer's point of view "" and vbNullString are simply empty strings. We've already mentioned why there is a specialised representation

>many things will see vbNullString and "" as the same, as you say, mostly they behave in exactly the same way .

Well … yes. They should all behave in exactly the same way. It is part of the requirement in using BSTR. To quote Microsoft : “you are required to accept NULL as a valid BSTR and treat it the same as a pointer to a zero-length BSTR”

You may already have seen this in your wanderings, but it is a pretty comprehensive discussion of VB(A) strings. The link is to Part 2, since that seems the most appropriate section for this current discussion (but the rest of the document is pretty good too): Optimize string handling in Visual Basic 6.0 - Part II

>not so sure why you refer to the StrPtr( ) as a trick

I didn’t say StrPtr was a trick! I said there are tricks for getting the same result, eg

VarPtr(ByVal a)

instead of

StrPtr(a)

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

Confused with VBA and VB variable addresses and pointers and A W ANSIs and Unicorn beasts

Post by DocAElstein »

Thanks. I recognise the aivosto site, I think I wandered past it, but somehow missed seeing anything relevant at the time.
I see now a few small bits of part I and the start of part II, and a good chunk of the middle to end bit of part II is indeed very relevant and interesting to me just now, so thanks for the pointer… Understanding what is going on is for me is the most important thing just now.
It was not a difficult article to read. Partly perhaps as it was saying some things I finally figured out quite well. It was good to see.

A few initial observations from reading that aivosto you pointed me to :

BSTR
As for what a BSTR is. This is that article's variation: VB String is a BSTR, BSTR is the COM datatype for a string pointer. (The pointer points to the first character of the datastring, not to the length prefix.)
For me, for now, the best thing to say is that BSTR is the middle chunk from my diagrams.
So another good international standard definition I would suggest should be: A BSTR is the middle bit of Alan’s beautiful diagrams showing the chunks of memory involved in storing a String in VB(A)
But I may modify that when I go retro, and do some VB6 experiments( going retro I have learned the hard way seems, unlike in most technologies, never a bad thing with Microsoft stuff, and often the best option ). Maybe from now I will force myself to dust off and place at least one VB book every day on a make shift heavy duty shelf I made for them.

VbNullString( null string ) v "" (empty string/ zero length string) and String memory representations
Encouragingly it seems to say very similar to me, even the string memory representations diagrams are like mine, ( no where near as beautiful though, not a COFFee table in site ). The less pretty diagrams there are however, understandably, missing my extra bottom chunk for the first ( VB(A) ) pointer , so I am not sure how accurate a representation that (my pretty diagram at the bottom) is.

API calls with Unicode strings and MyAPIFunctionA v MyAPIFunctionW issues
Some interesting stuff here, again confirming something I figured out the hard way, and then went on after to find just a few places/ people talking about it……
In particular in a quote from there …. VB6 doesn't directly support the Unicode 'W' functions
Now, I am still thinking that MyAPIFunctionA and MyAPIFunctionW have actually been around for about the same time, possibly exactly the same time, - I am still not totally sure about that****.
My experiments suggest also that VBA doesn't directly support the Unicode 'W' functions either,( sort of. VBA or VB may be talking about the same thing here### )
We need to be very careful what we are talking about here. The MyAPIFunctionW are there available, (and probably always were****.)
But API seems to have some preference to do "ANSI" ( if you pardon the historical mismomer permutation ) where strings are concerned. So it has some automatic things it does to convert strings to "ANSI". Playing around with StrPtr( ) / pointer workarounds gets us over this problem. I done it now many times, so I know how to do it consistently successfully , for example to get some API stuff getting/ using the full range of "Unicorn" characters.
It seems all a bit peculiar and still confusing to me. It would appear ( a bit of a guess on my behalf because of not finding out anything for sure) that regardless of A or W version, VB does a conversion to "ANSI" on any strings, then Microsoft you say, say the ANSI version internally translates the string to Unicode. Whether the W version does that or not I don’t know yet. I still don’t know much about the difference.
It is perhaps unnecessarily confusing, as the info comes out in the literature in drips and drabs, tit bits and riddles. For example in that aivosto bit on " API calls with Unicode strings " it says .. VB6 doesn't directly support the Unicode 'W' functions…. That is an imprecise riddle, instead of telling it straight, one which snb would be proud of, as its open to interpretation as you chose.
Having said that i think I am close in straightening it all out, for the greater benefit of mankind, and me if I am lucky.

I need to / want to make sure I understand this apparent automatic "Unicode To ANSI . ANSI to Unicorn" conversion or whatever it is, a bit better.

For one reason I need to / want to, understand better because I found a German Guy in the VBA API fraternity telling a lot of people, that VBA runtime does all this "ANSI A Unicorn W back and forth" when we use strings in API in VBA, (VBA Marshelling he calls it), and he gets famous saying that he discovered it. I might want to set him straight, (or not if he is right).
_ I don't think he did not discover it: Possibly he just did not find the stuff I either found myself or was pointed to from help here*. (*I discovered something similar myself as well, but then after I read the other stuff talking about. )
_ But maybe saying VBA runtime does it might be technically correct , sort of??, … VB runtime is doing it, but VBA is implementing string stuff using VB stuff?###. I need to think a bit more about that later


I must go now and prepare my Xmas trees for the local authority collection tomorrow. I could just chuck them in a hedge at any time (in the evening) as I live on the town edge, but it’s just a fun tradition here the town collecting them in their little truck, - they collect the normal rubbish in their big modern truck early as ever, but then after, tomorrow , come back later in overtime in their quaint little truck for the trees, and I like to see them carrying my oversize trees away, its like a scene from that Chevy Chase family Griswold Christmas Film, ( and I have to pay part of my rubbish collection fees for it anyway , whether they do it or not)

Thanks again
Alan
Regards , Ālan , DocÆlstein :england: , :germany:

User avatar
SpeakEasy
5StarLounger
Posts: 722
Joined: 27 Jun 2021, 10:46

Re: Confused with VBA and VB variable addresses and pointers.

Post by SpeakEasy »

>VB does a conversion to "ANSI" on any strings, then Microsoft you say, say the ANSI version internally translates the string to Unicode

Yep! But let's be more explicit. VB translates the underlying Unicode string to ANSI when passing a string the the API. ANSI API functions then translate that to Unicode, and upon return from the API call the Unicode strings are translated back to ANSI - which VB then turns back into Unicode ... fun, eh?

Here, have an experiment designed to confuse you ...

Code: Select all

Option Explicit

Private Declare Function StrTrim Lib "shlwapi.dll" Alias "StrTrimA" (ByVal psz As String, ByVal pszTrimChars As String) As Long ' we'll be passing vb string to api
Private Declare Function StrTrimTrick Lib "shlwapi.dll" Alias "StrTrimA" (ByVal psz As Long, ByVal pszTrimChars As Long) As Long ' we'll be passing the StrPtr to API

Public Sub trimmy()
    Dim a As String
    Dim b As String
    
    a = "Hello" & ChrW(257) ' add a non-extended ASCII (i.e non 'ANSI') unicode character
    b = a
    
    Debug.Print a
    Debug.Print a = b
    Debug.Print AscW(Right(a, 1))

    StrTrim a, "" ' call an 'ANSI' API function that does nothing to a string, so we'd expect the same string we passed in ...
    Debug.Print a
    Debug.Print a = b ' Oh
    Debug.Print AscW(Right(a, 1)) ' Oh dear
    
End Sub

Public Sub trimmy2()
    Dim a As String
    Dim b As String
    
    a = "Hello" & ChrW(257) ' add a non-extended ASCII (i.e non 'ANSI') unicode character
    b = a
    
    Debug.Print a
    Debug.Print a = b
    Debug.Print AscW(Right(a, 1))

    StrTrimTrick StrPtr(a), StrPtr("") ' call 'trick' version of 'ANSI' API function that does nothing to a string, so we'd expect the same string we passed in ...
    Debug.Print a
    Debug.Print a = b ' hurrah
    Debug.Print AscW(Right(a, 1)) ' as we'd expect
    
End Sub

User avatar
HansV
Administrator
Posts: 79952
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: Confused with VBA and VB variable addresses and pointers.

Post by HansV »

:hairout:
Best wishes,
Hans

User avatar
SpeakEasy
5StarLounger
Posts: 722
Joined: 27 Jun 2021, 10:46

Re: Confused with VBA and VB variable addresses and pointers.

Post by SpeakEasy »

(and, by the way, trimmy2 should be a concern, rather than any sort of reassurance)

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

Re: Confused with VBA and VB variable addresses and pointers.

Post by DocAElstein »

SpeakEasy wrote:
10 Jan 2025, 12:20
.Here, have an experiment designed to confuse you ...
Thanks.
... OK, I’m game.
I am confused perhaps, in parts. But possibly not too much. …. If you had given me these gifts a month ago I would be a lot more confused, and at that characteristic higher level of confusion that is more typical for me

This first
VB translates the underlying Unicode string to ANSI when passing a string the API.
ANSI API functionA's then translate that to Unicode, and upon return from the API call the Unicode strings are translated back to ANSI ,
which VB then turns back into Unicode ..

This makes some sense based on a recent enlightenment a few posts above ,… Internally, the ANSI version translates the string to Unicode

So that would have been my guess for the full stroy. But I would have not known for sure, but now I do, which is very helpful in reducing another uncertainty in my equation to figure out what the hell is going on, so Thanks.
( Would be nice to have the corresponding full story for the Unicorn API functionW's , :smile: )

_._____________________-

For the coding gifts , I have just slightly reorganised them for me to talk my way through them. But they are basically the same as your (Mike's (SpeakEasy's) ) gifts. ( I also added a third, but that is almost identical to the second )

Coding here , and in uploaded file in code module WombatsConfusions

I think I am close, at least in parts, to understand what is going on.
This is my best take on it so far:

Rem 1, which is approximately the first half of the codings before the API call, has no surprises for me. VBA does Unicorn**, but the VB Editor, which includes the Immediate window, does not,- it’s got stuck for some historical reason in "ANSI".
If you ignore the Immediate window output then all makes sense in Rem 1
In more detail: If you try to output a Unicorn character to the Immediate window, then you more often than not get a ? , but sometimes instead of a ? , you get a character that is not the one you expect. When you get a unexpected character rather than a ? , then, I am not sure why. Possibly one of these two reasons:
_ that is by chance when that what the Immediate window gets coincidentally matches a valid "ANSI"
, or
_ some other extra innards and entrails has a list of unexpected "ANSI"s that it knows belongs to something looking like a "ANSI", so it gives that similar "ANSI" instead, so as to cunningly make you think you are seeing the character you expected.
( In the Excel spreadsheet, which does Unicorn, as far as I can tell very well, (as does Eileen's Lounge fortunately), you will see the Unicorn ā for the ChrW(257) , but in the Immediate window you will see the simple Ascii "ANSI" a , ( a being code point decimal number 97 - Chr(97), ChrW(97) is mapped to character a )

Rem2 in the first gift, ( my Sub JimmyJimmyRiddleA() ) , which is approximately the second half of the coding, the bit that calls the win32 API function…….
The best explanation I have so far for this is that something similar goes on to what happens in the Immediate Window in one of the Unicorn to "ANSI " conversions, perhaps the first one from here VB translates the underlying Unicode string to ANSI when passing a string the API.
ANSI API functionA's then translate that to Unicode, and upon return from the API call the Unicode strings are translated back to ANSI ,
which VB then turns back into Unicode ..


After that you have the simple Ascii "ANSI" a which any further "ANSI" to Unicorn conversion, ( or any other conversions you like to try) will leave you with the simple Ascii "ANSI" a

_._______________

To explain the second gift, …….. you will see that in my version, Sub JimmyJimmyRiddleAW() it is almost identical to my extra third coding, Sub JimmyJimmyRiddleW() .
I will have a long musing somewhere on the typical third coding type, if I ever fully figure it out, but the TLDR is that it is the standard trick to get API to do Unicorn in VB(A), (which since a few weeks I can do consistently, but have not quite figured out the full story as to how it works). The approximate story is that it prevents one or more of the conversions as it or they( the automatic conversions) are done on strings, but it or they are not done on Long pointers or Long pointers (– no typo there on the repeated bit )
The TLDR to the trick is that you
_(i) use the Unicorn version ( The W instead of the A version ) of the API
and
_(ii) use long pointers or long pointers in place of the string parameters (once again no typo in the repeated words there)

What is perhaps of "concern" here is that in the second gift , and my second coding, we do the _(ii) pointer bit but we 'aint using the W API version, ( well perhaps we implicitly are **)
In my experience so far that would not work if we used the "ANSI" API version and not the Unicorn API version.
In this case, perhaps something from the documentation explains what is going on ….. The shlwapi.h header defines StrTrim as an alias that **automatically selects the ANSI or Unicorn version of this function based on the definition of the UNICODE preprocessor constant

( The UNICODE preprocessor constant codswallop will, of course, be familiar to all of us, :scratch: :innocent: :frown: :smile: )

_.____

How did I do, marks out of 10?
( I think I will have this all figured in a few days , or a few weeks, enlightments dependant :smile: )


ālan
( DocÆlstein )
_._____________


**Unicorn is the Generical name for anything related to Unicode or Unicode Encodings, to avoid mismomers, (historical or otherwise), in the use of the word Unicode. (I have not figured out an amusing one for the historical ANSI misnomer yet)

Share ‘VBA Windows API VB Strings.xls’ https://app.box.com/s/naoxb5e0u3vlqgokmu1w3t0mx5jrrvv3
Regards , Ālan , DocÆlstein :england: , :germany:

User avatar
SpeakEasy
5StarLounger
Posts: 722
Joined: 27 Jun 2021, 10:46

Re: Confused with VBA and VB variable addresses and pointers.

Post by SpeakEasy »

>If you ignore the Immediate window output then all makes sense in Rem 1
This is why I additionally used the AscW function to display the last character (which we deliberately set to be non-ansi),. And AscW correctly returns that value until we pass it to the no-operation StrTrimA, after which it returns an extended ASCII code instead ...

>some other extra innards and entrails has a list of unexpected "ANSI"s that it knows belongs to something looking like a "ANSI", so it gives that similar "ANSI"

Ok, so we are talking here about what VB does when it receives (what it thinks is) a Unicode string from an ANSI Win32 function. Basically, internally WideCharToMultiByte (google it) is called for the string against the current codepage. Some extended ascii characters may appear in the code page, and thus get remapped. Of course the knock-on effect of this is exactly which characters get remapped and what to depends on which code page is in use.

>the Excel spreadsheet, which does Unicorn

So does MS Forms ...

> The shlwapi.h header defines StrTrim as an alias that **automatically selects the ANSI or Unicorn version of this function based on the definition of the UNICODE preprocessor constant

Nope. Preprocessor constants have nothing to do with VB; this is for C (essentially it is the equivalent of the aliases VB uses).

User avatar
DocAElstein
5StarLounger
Posts: 748
Joined: 18 Jan 2022, 15:59
Location: An Englishman, illegally re-routing rivers, in Hof, Beautiful Bavaria. Rule, Britannia!

Re: Confused with VBA and VB variable addresses and pointers.

Post by DocAElstein »

Thanks for the reply, it's helping me to get there, ( I don't exactly know where I'm going. (But I sure know where I've been, … and the journey is often the best bit ….) )
_.___
SpeakEasy wrote:
11 Jan 2025, 01:14
...
This is why I additionally used the AscW function to display the last character (which we deliberately set to be non-ansi),. And AscW correctly returns that value until ...
Yep, I think I pretty well figured out all or most of what you where doing and why.
Everything I wrote was just me trying to figure out how/ why things were working.

_.__

So I think I figured out some or most of the first half , so I'll take 3-4 out of 5 for that, maybe.
The answer was that the Immediate Window don't do Unicorn, ( but ..... it is giving a ( I don't know if the WideCharToMultiByte stuff is relevant there or whether the WideCharToMultiByte stuff is only explaining the second half? ) )
_.________________________

I didn't figure out the second half fully, - …
....automatically selects the ANSI or Unicode version…. Is for C__ language, not VB - OK, thanks.

Using the long pointer stuff instead of a string gets us past the Unicorn to "ANSI" first conversion, when VB ( I think VB and not VBA) does that … - or at least I think I got that bit right.

The WideCharToMultiByte I will have a good think about in a day or two, - (I need to go away now for a day or two
and help keep the current developing Forth Reich here in check, or we will all be in trouble )

_._____
SpeakEasy wrote:
11 Jan 2025, 01:14
.... > the Excel spreadsheet, which does Unicorn
So does MS Forms ...
OK, I did Know that. I have not done much at all with MS Forms


Thanks
Alan
Regards , Ālan , DocÆlstein :england: , :germany: