POINTERs

Anonymous
2019-01-23
2022-09-26
  • Anonymous - 2019-01-23

    Originally created by: ph0010421

    Hello
    I have a GlobalVariable table with just BOOLs.
    I'd like to loop through each BOOL. The list will change as the application develops, so I was hoping to make a pointer to the first VAR and a pointer to the last VAR and loop through them.
    I the ADR() of the VAR is not based on the position in the table though, rather the order they are added.
    Is there a technique to look at all the VARs in a table?

    I know I could make an ARRAY of BOOL, but I have my reasons to keep them as individual vars.
    Thanks

     
  • Lo5tNet - 2019-01-23

    It might be possible the way you are describing but I have always used a structure to hold something like that. For example:

    Your structure would look like this and can be expanded as needed.

    TYPE TABLEBOOLS
    STRUCT
        xBool1        :    BOOL;
        xBool2        :    BOOL;
        xBool3        :    BOOL;
        ......
    END_STRUCT
    END_TYPE
    

    If you want to use a GVL you can declare it like:

    VAR_GLOBAL
    //Define global variable
        structTABLEBOOLS        :    TABLEBOOLS;
    END_VAR
    

    Then to loop through the structure you would do:

    VAR
        iCount        :    BOOL;
        pLocation    :    POINTER TO BOOL;
        pAdjustedLocation    :    POINTER TO BOOL;
        xValue        :    BOOL;
    END_VAR
    //Get address of structure
        pLocation := ADR(GVL.structTABLEBOOLS);
        
    //Loop through structure and store each value in xValue
        FOR iCount := 0 TO (SIZEOF(GVL.structTABLEBOOLS)-1) BY 1 DO
            pAdjustedLocation := pLocation + INT_TO_DWORD(iCount);    //This changes the pointers location.
            xValue := pAdjustedLocation^;    //This would give you the value of each bool as it iterates through the structure.
        END_FOR
    

    If you have different data types besides BOOL/BIT this method would not work. There would need to be more checking done for iterating through it properly.

     
  • Anonymous - 2019-01-23

    Originally created by: ph0010421

    Thanks ComingBack4U.
    I like that idea

     
  • Anonymous - 2019-01-24

    Originally created by: rickj

    @Comingback4u's method is platform/compiler dependent. Struct members are not necessarily packed in a contiguous manner on all CPU architectures.

     
  • dFx

    dFx - 2019-01-24

    Why not using an array with a constant defining the length ?
    Then access may be done by an ENUM, defining each value your array index may take.

    For instance,

    VAR_GLOBAL
       MyBool : ARRAY [1..Const._MAXVALUE] OF BOOL;
    END_VAR
    
    TYPE MyBools_ENUM :
    (
       First := 0,
       Second:= 1,
       Third:= 2,
       WhatEver := 3
    ) UINT;
    END_TYPE
    

    Then usage is in a loop, as a standard array or this way :

    MyBool[MyBools_ENUM.WhatEver] := 99;
    
     
  • jzhvymetal - 2019-01-24

    First understand Codesys treats bools as one byte. So you can not pack the bits unless you locate them to physical memory. I already have many post on this so I will not repeat it here.

    Also Codesys does not allow for array of pointers or references but here is work around by making an array of structures with the pointer or reference. I prefer references because you do not have to keep dereferencing them like pointers. See Example below that will the number of on bools.

    TYPE DUT_REF :
    STRUCT
       xBool: REFERENCE TO BOOL;
    END_STRUCT
    END_TYPE
    
    PROGRAM TEST
    VAR
       myref: ARRAY[0..7] OF DUT_REF;
       BIT00: BOOL;
       BIT01: BOOL;
       BIT02: BOOL;
       BIT03: BOOL;
       BIT04: BOOL;
       BIT05: BOOL;
       BIT06: BOOL;
       BIT07: BOOL;
       i: INT;
       num_of_on: UINT;
    END_VAR
    
    myref[0].xBool REF= BIT00;
    myref[1].xBool REF= BIT01;
    myref[2].xBool REF= BIT02;
    myref[3].xBool REF= BIT03;
    myref[4].xBool REF= BIT04;
    myref[5].xBool REF= BIT05;
    myref[6].xBool REF= BIT06;
    myref[7].xBool REF= BIT07;
    BIT00:=TRUE;
    BIT06:=TRUE;
    BIT07:=TRUE;
    num_of_on:=0;
    FOR i:=0 TO SIZEOF(myref)/SIZEOF(DUT_REF)-1 DO
       IF __ISVALIDREF(myref[i].xBool) THEN
          IF(myref[i].xBool) THEN 
             num_of_on:=num_of_on+1; 
          END_IF   
       END_IF
    END_FOR;
    
     

    Related

    Talk.ru: 1
    Talk.ru: 2
    Talk.ru: 3
    Talk.ru: 5
    Talk.ru: 7

  • Anonymous - 2019-01-24

    Originally created by: scott_cunningham

    Please take care with pointer and reference assumptions - as was warned by others regarding memory locations! The following screenshots show issues in the idea that a list of BOOLs will be where you expect them:

    This was at first build and download - note the huge gap between Bool1 and Bool2 (so reading one memory location after Bool1 would be complete garbage!):

    This was after I added another BOOL and performed an online change - notice Bool3 is spaced 4 bytes after Bool2:

    This was after I performed a clean and download - note that Bool3 is now moved relative to the online change (and is as one would "expect" - at 1 memory location after Bool2):

    If you are going to use a solution using POINTER TO or REFERENCE TO, please know that online changes can sometimes move variables and FBs around in memory, breaking those pointers (point to the old location, not the new one) - refresh the pointers to avoid online change problems (you can avoid online changes, but somebody else using your code may use online change...). I am pretty sure REFERENCE TO has the same problem with online change, since behind the scenes a REFERENCE TO is a special handling of POINTER TO.

    Good luck!

    IMG: pointer

    IMG: pointer

    IMG: pointer

     
  • Anonymous - 2019-01-24

    Originally created by: KevinR

    Wow - Scott, Thank you for this detailed description.

    Gesendet von meinem LYA-L29 mit Tapatalk

     
  • Lo5tNet - 2019-01-25

    Scott,
    I understand your example of just creating a BOOL and how there is no guarantee that bool2 will be right after bool 1 but isn't that where using a structure would fix that?

    For example whenever I change the structure and do an on-line change you get a warning that the variable you declared that used that structure will move to new memory locations. This moves all of the existing variables in the structure and keeps them in order. I have yet to find a device/os/compiler that doesn't put this in order when talking about CoDeSys.

    I'm trying to understand how to do what the original author was asking if the way I suggested is not reliable. Just trying to learn.

    Regards,
    CB

     
  • Anonymous - 2019-01-25

    Originally created by: scott_cunningham

    CB
    A STRUCT should be one continuous space IF the struct elements are all the same (such as a struct if BOOLs). This becomes false when you mix data types (DWORDS don’t start at an odd memory location).

    I also received the “warning” message when I made the online change with Bool3, but I simply did what too many people do - I quickly clicked OK and ignored it!

    Your offered solution is good, with a small change - I would not use +1 in your pointer math - that assumes that a BOOL will always only use one byte of memory location... this may not be the case on all hardware platforms! (This may seem silly, but so does CoDeSys’ BOOL as 8 bits of space instead of 1 bit to a C programmer!). Instead, use + SIZEOF(BOOL) in the for loop and the pointer calculation.

    It would be interesting to see some type of OOP solution, too! Seems close to a linked list.

     
  • Lo5tNet - 2019-01-25

    Thanks Scott,
    Great suggestion. I hadn't thought of using sizeof to determine the length of a data type for iterating through memory locations.

    Regards,
    CB

     
  • Anonymous - 2019-01-25

    Originally created by: ph0010421

    Comingback4u hat geschrieben:
    Thanks Scott,
    Great suggestion. I hadn't thought of using sizeof to determine the length of a data type for iterating through memory locations.
    Regards,
    CB

    Agree. Thanks Scott

     
  • e60newbie - 2022-09-26

    use {attribute 'subsequent'}
    and this problem is solved

     

Log in to post a comment.