Announcement

Collapse
No announcement yet.

Strings and Pointers Verification

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Strings and Pointers Verification

    I was checking out the forums to see what problems others have (maybe help where I can), and I think I tripped into something that reminded me of a problem I have had (or maybe currently have) and do not know it.

    over in Control Get Text in SDK? about getting text from a control written in SDK to be used in a DDT program, I noticed that Fred Harris mentions:
    If you dimension a dynamic string variable [b/]and nothing is assigned to it[/b] then no memory to put anything has been allocated. That is why Byval Strptr(var) crashes. The api will start moving characters to an invalid location. That is why most api programmers use asciiz variables heavily in their code. In the situation above with your code, it makes more sence to dimension an asciiz variable long enough to hold the string, then just put that in the function call. Since basic's default parameter passing mechanism is a pass by reference, the address of the asciiz string will be passed to the Api - and that is what it wants - an address where it can start copying characters to.
    key points jumped out at me..."What IF????"

    *** WARNING *** The below is my BAD attempt at describing what I am wondering, so please no "Holy-Wars" over my incorrect terminology or mis-phrasing
    1. In my past I tried to stay away from pointers, asciiz, and anything I did not understand as much as I could (yep I am a VB refugee)
    2. What I did not realize was passing a variable was by default "BYREF" and not the "BYVAL" idea (aka a "Hello World", I did not know I was passing a pointer and not the words "Hello World")
    3. I used globals for variables that had to be passed among many functions (and yes I do know now that many functions could be changing the variable at the same moment and cause a problem)
    4. In the below the use of DIM I know can be easily misconstrued with declaring a variable


    That said Dim vs declaring (mixed terminology) lets say for simplicity sake, if I have a global declared as string, and one of my functions use that variable, and I have not put anything into the variable yet, does this use a invalid location (that Windows or compiler or whatever) may or may not forgive me and not cause a problem (until it causes a problem)?

    Hopefully not TOO confusing if you get what I am trying to ask, but I know I confused myself trying to describe how to ask
    Engineer's Motto: If it aint broke take it apart and fix it

    "If at 1st you don't succeed... call it version 1.0"

    "Half of Programming is coding"....."The other 90% is DEBUGGING"

    "Document my code????" .... "WHYYY??? do you think they call it CODE? "

  • #2
    In using a String as a parameter, whether or not the string is empty or actually is holding some positive number of characters, i.e., the string data, no data is ever really moved or copied to anywhere. What gets moved or copied is a string descriptor, i.e., a sort of info record on the string that contains such info as the length of the string, where its actual data is actually lying in memory, and so forth. If in a procedure to which the string is passed, an actual assignment to the string occurs involving the equal sign, then PowerBASIC will do its string machinery magic and the string will actually have a contents that can then be accessed in that procedure where it was passed, and later in the original calling routine. Slick, Huh!

    So no, it sounds to me like you're OK. Strangely enough I have already found myself putting globally declared variables in parameters to functions, and then I always ask myself why in the world am I doing that? A globally declared variable is visible throughout the program anyway.
    Fred
    "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

    Comment


    • #3
      Here is a program even a bit more complicated than the one you described Cliff that uses an array of strings where the string assignments occur in the procedure itself. Note that I used PB's LBound and UBound keywords to prove that the routine to which the string array was passed knew everything about that string array, even though it wasn't even dimensioned there. Maybe tomorrow if I have time I'll redo that little program in C showing all the guts and gory details of what needs to be done to reconstruct something like this in C. However, once you do it in a really low level language like C or assembler, you really get to see everything that is going on. The magic is in the Basaic String machinery and the string descriptor mechanism

      Code:
      #Compile Exe
      #Dim All
      
      Sub DoSomethingUseless(strData() As String)
        Register i As Long
        
        Print "LBound(strData,1)="LBound(strData,1)
        Print "UBound(strData,1)="UBound(strData,1)
        Print
        strData(0)="Fred"
        strData(1)="Sam"
        strData(2)="Edward"
        For i=LBound(strData,1) To UBound(strData,1)
          Print i,strData(i)
        Next i
      End Sub
      
      Function PBMain() As Long
        Local strNames() As String
        
        Redim strNames(2) As String
        Call DoSomethingUseless(strNames())
        Erase strNames
        Waitkey$
        
        PBMain=0
      End Function
      
      'LBound(strData,1)= 0
      'UBound(strData,1)= 2
      '
      ' 0            Fred
      ' 1            Sam
      ' 2            Edward
      And interestingly, this will give you the exact same output.

      Code:
      #Compile Exe
      #Dim All
      
      Sub DoSomethingUseless(strData() As String)
        Register i As Long
        
        Print "LBound(strData,1)="LBound(strData,1)
        Print "UBound(strData,1)="UBound(strData,1)
        Print
        strData(0)="Fred"
        strData(1)="Sam"
        strData(2)="Edward"
      End Sub
      
      Function PBMain() As Long
        Local strNames() As String
        Local i As Long
        
        Redim strNames(2) As String
        Call DoSomethingUseless(strNames())
        For i=LBound(strNames,1) To UBound(strNames,1)
          Print i,strNames(i)
        Next i
        Erase strNames
        Waitkey$
        
        PBMain=0
      End Function
      
      
      'LBound(strData,1)= 0
      'UBound(strData,1)= 2
      '
      ' 0            Fred
      ' 1            Sam
      ' 2            Edward
      Last edited by Fred Harris; 31 Jan 2008, 09:39 PM.
      Fred
      "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

      Comment


      • #4
        "DIM [scalar or dynamic string variable]" allocates nothing. It is a compiler-directing statement only. (Tells compiler what the symbol - IF IT APPEARS in executable code within its scope - means.). If the variable is used, then space is reserved in the default data segment (STATIC or GLOBAL) or on the stack (LOCAL). (I don't know how THREADED are handled).

        DIM [array] is different.

        getting text from a control written in SDK to be used in a DDT program
        Boy, you'd think by now someone might have said something here about being careful when mixing and matching coding styles.

        In the case of getting text, yes you have to be careful, but it turns out that using GetDlgItemText or GetWindowText with a handle to a DDT-created window is perfectly within the rules, as said "DDT handles" are documented as being valid Windows handles to the same object.

        That being the case, any problems arising from the use of GetWindowText or GetDlgItemText must arise from the programmer's failure to understand..
        A. The SDK documentation for the calll
        and
        B. The fundamentals of using the PB compilers.

        And this stuff is "Programming with the PowerBASIC Compilers" One-Oh-One.

        MCM
        Michael Mattias
        Tal Systems Inc. (retired)
        Racine WI USA
        [email protected]
        http://www.talsystems.com

        Comment

        Working...
        X