Page 1 of 1

StructuredUnion(s)

Posted: Sun Jul 04, 2004 8:45 pm
by NoahPhense

Code: Select all

Structure Type
  Name$
  StructureUnion
    Long.l      ; Each field (Long, Float and String) resides at the
    Float.f     ; place in memory.
    String.s    ;
  EndStructureUnion
EndStructure
I'm trying to get a grasp on the above.. any information will help.. thx

- np

Posted: Sun Jul 04, 2004 9:32 pm
by GPI
With StructureUnion you can create "Aliases"

Code: Select all

Structure Combined
  StructureUnion
    x.l
    PosX.l
    dx.l
  EndStructureUnion
  StructureUnion
    y.l
    posy.l
    dy.l
  EndStructureUnion
EndStructure

Typ.Combined
Typ\x=10
Typ\y=20
Debug Typ\dx
Debug Typ\PosX
Debug Typ\dy
Debug Typ\posy
\x, \dx, \PosX are diffrent names for the same position in the structure.

In your example above, you create alias-names, but with diffrent typ (and btw. StructureUnion with String and other Variable-Typ combined isn't a good idea (my opinion)).

Re: StructuredUnion(s)

Posted: Sun Jul 04, 2004 10:20 pm
by tinman
NoahPhense wrote:I'm trying to get a grasp on the above.. any information will help.. thx
All the variables inside a union are located at the same address in memory. The size of the union (in bytes taken up by it) is the size of the largest item inside the union.

There are many uses for such a thing. For example, in the code you posted there was a string, long and float in the union. This would allow you to store any of those types at that position in the structure, useful for e.g. creating a "variant" type (if you are familiar with VB).

Other possibilities are things like accessing the field in a different way. Again, using your example, you could access the string pointer directly by code such as this:

Code: Select all

DefType.Type foo
foo\String = "blah"
Debug foo\Long
Debug @foo\String
This can be used where you need the address of a string variable, rather than the string itself, since @whatever.s will give you the start address of the string.

Similarly, you may want to fiddle with the bits which represent a floating point number. Since you cannot use bitwise operators (&, |, etc) on floats in PB, you could use the \Long field from your structure to access the bits of \Float directly.

Posted: Sun Jul 04, 2004 10:25 pm
by jack
what tinman said, for example:

Code: Select all

Structure myfloat 
  StructureUnion 
    fnumber.f 
    fbyte.b[4]      
  EndStructureUnion 
EndStructure 

x.myfloat
x\fnumber=3.141593
you can now access each byte in the float like this:

Code: Select all

print(hex(x\fbyte[1])) ;fbyte[1] through fbyte[4]
:)

..

Posted: Sun Jul 04, 2004 11:36 pm
by NoahPhense
GPI wrote:With StructureUnion you can create "Aliases"
StructureUnion with String and other Variable-Typ combined isn't a good idea (my opinion)).
Excellent help guys.. thanks.. as for this example, it came from the PB
Help File.. ;)

Ok, I've done some testing with everyones examples. Which is 99% of
how I grasp new things.

Code: Select all

Structure Type 
  Name$ 
  StructureUnion 
    Long.l      ; Each field (Long, Float and String) resides at the 
    Float.f     ; place in memory. 
    String.s    ; 
  EndStructureUnion 
EndStructure

DefType.Type foo

foo\Name$ = "PB"
Debug foo\Name$

foo\String = "blah" 
Debug foo\String          ; the string
Debug @foo\String         ; the address
Debug PeekS(@foo\String)  ; pull string from address

foo\Float = 1.234
Debug foo\Float

foo\Long = 8765
Debug foo\Long

; So as you've stated, they are kind of like alias's.  They can be
; utilized how ever you wish, as long as you have defined them
; first with StructureUnion.
;
; Is the main advantage of this, to save on memory(size)?
Here is the one that I was analyzing:

Code: Select all

    Structure IPType
      Reserved.w
      Port.w
      StructureUnion
        IPLong.l
        IP.b[4]
      EndStructureUnion
      Zeros.l[2]
    EndStructure

    length.l = SizeOf(IPType)
    result.l = getpeername_(cnid, @IP.IPType, @length)

    If result = 0
      remoteip$ = StrU(IP\IP[0],#Byte)+"."+StrU(IP\IP[1], #Byte)+"."
      ;remoteip$ + StrU(IP\IP[2],#Byte)+"."+StrU(IP\IP[3], #Byte)+":"+StrU(IP\Port,#Word) ;remote port
      remoteip$ + StrU(IP\IP[2],#Byte)+"."+StrU(IP\IP[3], #Byte); without remote port
    Else
      result = WSAGetLastError_()
    EndIf

    result.l = getsockname_(cnid, @IP.IPType, @length)

    If result=0
      localip$ = StrU(IP\IP[0],#Byte)+"."+StrU(IP\IP[1], #Byte)+"."
      ;localip$ + StrU(IP\IP[2],#Byte)+"."+StrU(IP\IP[3], #Byte)+":"+StrU(IP\Port,#Word) ;local port
      localip$ + StrU(IP\IP[2],#Byte)+"."+StrU(IP\IP[3], #Byte) ; without local port
    Else
      result = WSAGetLastError_()
    EndIf
Which will bring me to my next question:

In this line:

Code: Select all

result.l = getpeername_(cnid, @IP.IPType, @length)
Where he writes @IP.IPType is this where he is creating IP?

Instead of creating it first and then pointing to it like such?

IP.IPType or DefType.IPType IP
result.l = getpeername_(cnid, @IP.IPType, @length)

I just wasn't aware that you could create it and point to it in the same
command set. But its functional so I guess that's a yes.

-- and lastly, just to be sure that I understand StructureUnions

Code: Select all

Structure myNewType
  a.s
  b.s
  c.s
  StructureUnion 
    There.l
    Can.w 
    Be.s
    Only.b
    One.f
  EndStructureUnion 
EndStructure 

Sector1.myNewType

Sector1\a = "I love it when"
Debug Sector1\a

Sector1\b = "I learn new ways"
Debug Sector1\b

Sector1\c = "to handle data."
Debug Sector1\c

Debug ""

Sector1\There = 11
Debug Sector1\There

Sector1\Can = -30000
Debug Sector1\Can

Sector1\Be = "not recommended" ; @PB: could you tell me more/why not recommended?
Debug Sector1\Be

Sector1\Only = 127
Debug Sector1\Only

Sector1\One = 22.33
Debug Sector1\One
- np

..

Posted: Sun Jul 04, 2004 11:42 pm
by NoahPhense
** Ok, how about SizeOf() .. ?

Code: Select all

Structure Person
  Name.s      ; string = 4
  ForName.s   ; string = 4
  Age.w       ; word   = 2
EndStructure

a.Person

Debug SizeOf(a) ; 10
Is that the reason it is equal to 10 4+4+2, and they are bytes, right?

So that structure only takes 10 bytes to (create) ?

How can you find out the size of your structures with data in them?

- np

Re: ..

Posted: Sun Jul 04, 2004 11:56 pm
by tinman
NoahPhense wrote:; Is the main advantage of this, to save on memory(size)?[/code]
Depends how you view it. Obviously, because the fields all occupy the same address in memory you cannot actually have them all storing different things at the same time. Your "1.234" will overwrite the "blah" string, and the "8765" will overwrite the "1.234".

IMO the main advantage is to access things in an alternaive way. But as I said, other people may want to use it as a generic type and be able to use it as any type of variable. For example:

Code: Select all

Structure variant
    type.w
    structureunion
        byte.b
        word.w
        ; etc
    endstructureunion
endstructure
Now you can pass a variable of type "variant" to a procedure, and if you set the "type" field correctly, your procedure can determine what action to take and how to interpret the data.
NoahPhense wrote:

Code: Select all

    Structure IPType
      Reserved.w
      Port.w
      StructureUnion
        IPLong.l
        IP.b[4]
      EndStructureUnion
      Zeros.l[2]
    EndStructure
Hmm, i'm sure there should be a proper type for that. sockaddr_in IIRC. Why do people re-invent the wheel so often? Anyhoo, I digress :)
NoahPhense wrote: In this line:

Code: Select all

result.l = getpeername_(cnid, @IP.IPType, @length)
Where he writes @IP.IPType is this where he is creating IP?

Instead of creating it first and then pointing to it like such?

IP.IPType or DefType.IPType IP
result.l = getpeername_(cnid, @IP.IPType, @length)

I just wasn't aware that you could create it and point to it in the same
command set. But its functional so I guess that's a yes.
Yes, the compiler will create the variable wherever you first use it, regardless of what you are doing to it at the time.
NoahPhense wrote: -- and lastly, just to be sure that I understand StructureUnions

Looks like you got it.






NoahPhense wrote:** Ok, how about SizeOf() .. ?

Code: Select all

Structure Person
  Name.s      ; string = 4
  ForName.s   ; string = 4
  Age.w       ; word   = 2
EndStructure

a.Person

Debug SizeOf(a) ; 10
Is that the reason it is equal to 10 4+4+2, and they are bytes, right?

So that structure only takes 10 bytes to (create) ?

How can you find out the size of your structures with data in them?

- np

Re: ..

Posted: Mon Jul 05, 2004 4:06 am
by NoahPhense
tinman wrote:..other people may want to use it as a generic type and be able to use it as any type of variable.
Could you show me a full example of how you would use a variant?
tinman wrote:Hmm, i'm sure there should be a proper type for that. sockaddr_in IIRC. Why do people re-invent the wheel so often? Anyhoo, I digress :)
;) I found it here.. viewtopic.php?t=7197

- np

Re: ..

Posted: Mon Jul 05, 2004 8:41 am
by tinman
Oops, forgot to answer your second part. About sizeof(), yes that's why it's 10 bytes. Yes it only takes 10 bytes to create. The size of a structure is completely independant of what data is in it (the string content is not actually part of the structure).
NoahPhense wrote:
tinman wrote:..other people may want to use it as a generic type and be able to use it as any type of variable.
Could you show me a full example of how you would use a variant?
Not really since it's not something I've looked into as I have no need for it. I know other people here have done it though.

Re: ..

Posted: Mon Jul 05, 2004 9:25 pm
by NoahPhense
Thanks Tin for all your help. I'm certain this thread will help lots of
others. I'm sure once I start implimenting them, I will be bugging you
some more. ;)

- np