About use of pointers
- Psychophanta
- Always Here

- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
About use of pointers
What is rather:
a=@"qwer"
or
*a=@"qwer"
And...
*hWnd=OpenWindow(0,300,300,500,300,0,"")
or
hWnd=OpenWindow(0,300,300,500,300,0,"")
a=@"qwer"
or
*a=@"qwer"
And...
*hWnd=OpenWindow(0,300,300,500,300,0,"")
or
hWnd=OpenWindow(0,300,300,500,300,0,"")
- Psychophanta
- Always Here

- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
Sorry Timo, it is not the matter.
I understand the use and meaning of * and @ prefixes in PB.
But the matter is that i've notice that some PB programmers use long type variables as pointers, and PB works fine with it, and this fact dislike to me.
For example, i have seen: something like a=@"name", or a=@pop$. PB must show an error before these kind of things.
Another example and curious. The other day, i noticed a strange thing:
in a program i wrote:
and sometimes (and only sometimes
) PB debugger gives an error saying: " 'WindowID' isn't a valid window descriptor ".
Logically, PB must show this error always, but not only sometimes when is executed.
If you write an asterisk (which would be more coherent) before hWnd, this error is never shown, and program works normally.
Thanx!
I understand the use and meaning of * and @ prefixes in PB.
But the matter is that i've notice that some PB programmers use long type variables as pointers, and PB works fine with it, and this fact dislike to me.
For example, i have seen: something like a=@"name", or a=@pop$. PB must show an error before these kind of things.
Another example and curious. The other day, i noticed a strange thing:
in a program i wrote:
Code: Select all
hWnd=OpenWindow(0,300,300,500,300,#PB_Window_SystemMenu|#PB_Window_TitleBar,"BINGO")
If hWnd=0
MessageRequester("Error","Something fails",0)
End
EndIf
If OpenWindowedScreen(hWnd,300,300,500,300,1,0,0)=0
MessageRequester("Error","Something fails",0)
End
EndIf
Logically, PB must show this error always, but not only sometimes when is executed.
If you write an asterisk (which would be more coherent) before hWnd, this error is never shown, and program works normally.
Thanx!
Actually, this is a thing, that i very much like on the PB language.
You don't have to care about, what it is you store somewhere, as long
as it fits where you put it. This means, you can put everything in a LONG
variable, no matter, if it is a handle, a pointer to a string, or just a number
you need to count something in your program.
Have a look at C for example. You have hell of a lot of different types
there, each for a different purpose, but most of them are just 32bit
variables, nothing else. And I really hate all those type conversions you
have to do there.
That's the good thing about PB. All that is 32bit variable, is just a long.
You can still use a pointer to store your Window handle, if you like, but
if not, you can just copy it to a LONG, and live happily ever after
To come back to your original question:
What is a pointer anyway?
Look at what the ASM output of PB shows us:
*Pointer is represented by "p_Pointer", and Variable.l is replaces by
"v_Variable", both are of dword type. So where's the difference?
Actually, ASM doesn't care about what's inside, just like PB does.
It is just the compiler, who complains on other languages. If the language
has strict rules in that matter, like C has, then the compiler will stop and
say: hey, this isn't a HANDLE, it's a HWND, make a conversion! (well,
he'd say something similar at least
)
I'm really glad the PB compiler doesn't do this.
I personally prefer using the Pointer symbol '*' only in places, where it
makes sense to me. Which is, at places, where you actually have a Pointer,
and also try to read, what is stored at where it points to. (which is what you never do with a Window handle for example). For example, you have
a pointer to a Structure of data. This is where it makes sense to me.
But this is up to the individual programmer. And this is my whole point:
If you like to use *hWnd, because it reminds you of, that this is a handle
or something, that's fine, that's the strong point of PB
Well, so much about that...
Timo
You don't have to care about, what it is you store somewhere, as long
as it fits where you put it. This means, you can put everything in a LONG
variable, no matter, if it is a handle, a pointer to a string, or just a number
you need to count something in your program.
Have a look at C for example. You have hell of a lot of different types
there, each for a different purpose, but most of them are just 32bit
variables, nothing else. And I really hate all those type conversions you
have to do there.
That's the good thing about PB. All that is 32bit variable, is just a long.
You can still use a pointer to store your Window handle, if you like, but
if not, you can just copy it to a LONG, and live happily ever after
To come back to your original question:
What is a pointer anyway?
Look at what the ASM output of PB shows us:
*Pointer is represented by "p_Pointer", and Variable.l is replaces by
"v_Variable", both are of dword type. So where's the difference?
Actually, ASM doesn't care about what's inside, just like PB does.
It is just the compiler, who complains on other languages. If the language
has strict rules in that matter, like C has, then the compiler will stop and
say: hey, this isn't a HANDLE, it's a HWND, make a conversion! (well,
he'd say something similar at least
I'm really glad the PB compiler doesn't do this.
I personally prefer using the Pointer symbol '*' only in places, where it
makes sense to me. Which is, at places, where you actually have a Pointer,
and also try to read, what is stored at where it points to. (which is what you never do with a Window handle for example). For example, you have
a pointer to a Structure of data. This is where it makes sense to me.
But this is up to the individual programmer. And this is my whole point:
If you like to use *hWnd, because it reminds you of, that this is a handle
or something, that's fine, that's the strong point of PB
Well, so much about that...
Timo
quidquid Latine dictum sit altum videtur
- tinman
- PureBasic Expert

- Posts: 1102
- Joined: Sat Apr 26, 2003 4:56 pm
- Location: Level 5 of Robot Hell
- Contact:
Pointer errors (passing the wrong thing) would be so much easier to find if PB had even the simplest type checking but, like C, you could still override it.freak wrote:variables, nothing else. And I really hate all those type conversions you have to do there.
Not very strict as you can just tell the compiler that it really is a different type. And it trusts you ;)has strict rules in that matter, like C has, then the compiler will stop and say: hey, this isn't a HANDLE, it's a HWND, make a conversion! (well,
he'd say something similar at least :wink: )
If you paint your butt blue and glue the hole shut you just themed your ass but lost the functionality.
(WinXPhSP3 PB5.20b14)
(WinXPhSP3 PB5.20b14)
- Psychophanta
- Always Here

- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
Hi, Timo.
Of course, you are right.
In fact a 32 bit pointer is a 32 bit number, there are not difference.
And it is good that PB compile don't find differences on it as do x86 processors.
I find this as an advantage of PB too.
The only disadvantage is when i watch PB code; i get a bit mess.
Perhaps it would be good that PB show a warning when assign a pointer to a long, but thinking again perhaps it would be an unnecessary complication.
About the "'WindowID' isn't a valid window descriptor" debugger message i explained you; this is the complete code:
OpenWindowedScreen() function fails only sometimes when code is executed.
But if you replace the window handler for *hWnd, then all run fine every times you execute it.
Why? Could be a bug?
Of course, you are right.
In fact a 32 bit pointer is a 32 bit number, there are not difference.
And it is good that PB compile don't find differences on it as do x86 processors.
I find this as an advantage of PB too.
The only disadvantage is when i watch PB code; i get a bit mess.
Perhaps it would be good that PB show a warning when assign a pointer to a long, but thinking again perhaps it would be an unnecessary complication.
About the "'WindowID' isn't a valid window descriptor" debugger message i explained you; this is the complete code:
Code: Select all
Procedure bingo()
BackColor(250,250,250)
FrontColor(0,0,0)
Box(0,0,500,300)
Locate (0,20)
DrawText("Push LMB for balls.")
DefType.b
Dim B(90)
For J=1 To 90:B(J)=J:Next
For J=90 To 1 Step -1:XX=Random(J-1)+1:C=B(XX)
Repeat
EventID.l=WindowEvent()
If EventID=#PB_EventRepaint ; If the user has resized the window or anything, we will repaint our graphic
ElseIf EventID=#PB_EventCloseWindow:Goto SAL
EndIf
;press-key positive edge detection:
ExamineKeyboard()
pk=KeyboardPushed(#PB_Key_All)
If pka<>pk:pka=pk;then edge detected
If pk<>0;then it was positive edge
pki=1
EndIf
Else;then not edge detected
pki=0
EndIf
Until EventID=#WM_LBUTTONDOWN Or pki=1
While XX<J:B(XX)=B(XX+1):XX+1:Wend
B(J)=C
po.w= 60 + 20 * Val(Left(StrU((90-J)/16,#Word),FindString(StrU((90-J)/16,#Word),".",1)+1))
pu.w= ((90 - J) & 15) * 30
Locate (pu.w,po.w)
DrawText(Str(B(J)))
Next
If MessageRequester("Bingo program","Another?"+Chr(10),#PB_MessageRequester_YesNo) = 6
bingo()
EndIf
EndProcedure
If InitMouse()=0 Or InitSprite()=0 Or InitKeyboard()=0; Or InitPalette(10) = 0
MessageRequester("Error", "Can't open DirectX 7", 0)
End
EndIf
hWnd=OpenWindow(0,300,300,500,300,#PB_Window_SystemMenu|#PB_Window_TitleBar,"BINGO")
If hWnd=0
MessageRequester("Error","Something fails",0)
End
EndIf
If OpenWindowedScreen(hWnd,300,300,500,300,1,0,0)=0
MessageRequester("Error","Something fails",0)
End
EndIf
StartDrawing(WindowOutput()):DrawingMode(0)
bingo()
SAL:
StopDrawing()
CloseScreen()
CloseWindow(0)
End
But if you replace the window handler for *hWnd, then all run fine every times you execute it.
Why? Could be a bug?
- Psychophanta
- Always Here

- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
Hmm, looks like not. See this short test:
If 'a' was a long, it would print 255, but it prints -1, because a is a byte.
Looks like DefType also is a compiletime thing, that doesn't care about
beeing inside a procedure.
Timo
Code: Select all
Procedure test()
DefType.b
EndProcedure
a = 255
Debug aLooks like DefType also is a compiletime thing, that doesn't care about
beeing inside a procedure.
Timo
quidquid Latine dictum sit altum videtur
- Psychophanta
- Always Here

- Posts: 5153
- Joined: Wed Jun 11, 2003 9:33 pm
- Location: Anare
- Contact:
I would like to throw in my two cents worth on this discussion: Type checking is often needed when locating obscure bugs in your code, because you are showing the compiler HOW you intend to use a given
variable, and based on that, the compiler can sport subtle errors where
a typed variable is being used in an unexpected manner (unexpected to
the compiler, that is).
When you dp not specify a type, you leave it to the compiler to make the decision for you. If by chance the compiler creates a BYTE type, and you later attempt to use the variable as a pointer, with a Long (32-bit) form, then you are in effect dereferencing what four consecutive bytes in memory might point to by chance. Lets say that you did assigned the following: a=123, then the compiler can, by rights, assume that a is a byte. If you then did a b=@a, then you would be in effect, attempting to use 123 ??? ??? ??? ( four consecutive bytes) as that memory address.
If, by chance, you had done this: a=278, then the compiler could have seen that you had to use some larger variable for (a byte can only go up to 255 in count). But now it could be a word. using b=@a would mean dereferencing (looking up the memory starting at giving address) where you would have 022 001 ??? ??? as the apparent memory reference. Note that for easier understanding, the byte values are given in decimal.
But again, this would be in error. Now, not having explored this yet on my own, I assume that such errors are possible. However, if you had forced a to a given type, by first using it as a.l=123 or *a=123, then you would have let the compiler know at that time that 4 bytes (32-bits) were the number of bits needed to represent a. The * format would have told the compiler that "since this is a pointer, then it is proper for it to use as a defererencing tool (to use with the @ symbol). That can help type usage enforcement. But even if a were defined as a long (a.l), the use of @a to dereference a memory address is permissable.
Now, having recognized the advantage of strong type checking, I do not agree that everyone needs to use this form, and PureBASIC allows you to go either way. Here is one reason why I feel as I do. If *a=0, then it represents the NULL character, string, or value sought after in certain situcations. NULL typically means "Undefined", or "I don't care what this parameter is" when passing it as part of a function call. If undefined, you might need to define it. If undefined, you might want to ignore it. But in a strong type checking environment, it may not be allowed to leave *a undefined or to attempt it to be equal to zero. You may not be able to do *a=0, for instance. Such checks do not occur on a.l, which initially is understood to have a value of 0 until assigned something else, and where a.l=0 is perfectly legal. So if the language was somewhat limited in its ability to handle NULL, and resisted allowing me to use *a=0, then I could do a a.l=0:b=@a and still enact a NULL-type capability.
I hope that makes sence, and that I am not in grevious error on how the PureBASIC compiler works in this respect.
variable, and based on that, the compiler can sport subtle errors where
a typed variable is being used in an unexpected manner (unexpected to
the compiler, that is).
When you dp not specify a type, you leave it to the compiler to make the decision for you. If by chance the compiler creates a BYTE type, and you later attempt to use the variable as a pointer, with a Long (32-bit) form, then you are in effect dereferencing what four consecutive bytes in memory might point to by chance. Lets say that you did assigned the following: a=123, then the compiler can, by rights, assume that a is a byte. If you then did a b=@a, then you would be in effect, attempting to use 123 ??? ??? ??? ( four consecutive bytes) as that memory address.
If, by chance, you had done this: a=278, then the compiler could have seen that you had to use some larger variable for (a byte can only go up to 255 in count). But now it could be a word. using b=@a would mean dereferencing (looking up the memory starting at giving address) where you would have 022 001 ??? ??? as the apparent memory reference. Note that for easier understanding, the byte values are given in decimal.
But again, this would be in error. Now, not having explored this yet on my own, I assume that such errors are possible. However, if you had forced a to a given type, by first using it as a.l=123 or *a=123, then you would have let the compiler know at that time that 4 bytes (32-bits) were the number of bits needed to represent a. The * format would have told the compiler that "since this is a pointer, then it is proper for it to use as a defererencing tool (to use with the @ symbol). That can help type usage enforcement. But even if a were defined as a long (a.l), the use of @a to dereference a memory address is permissable.
Now, having recognized the advantage of strong type checking, I do not agree that everyone needs to use this form, and PureBASIC allows you to go either way. Here is one reason why I feel as I do. If *a=0, then it represents the NULL character, string, or value sought after in certain situcations. NULL typically means "Undefined", or "I don't care what this parameter is" when passing it as part of a function call. If undefined, you might need to define it. If undefined, you might want to ignore it. But in a strong type checking environment, it may not be allowed to leave *a undefined or to attempt it to be equal to zero. You may not be able to do *a=0, for instance. Such checks do not occur on a.l, which initially is understood to have a value of 0 until assigned something else, and where a.l=0 is perfectly legal. So if the language was somewhat limited in its ability to handle NULL, and resisted allowing me to use *a=0, then I could do a a.l=0:b=@a and still enact a NULL-type capability.
I hope that makes sence, and that I am not in grevious error on how the PureBASIC compiler works in this respect.
has-been wanna-be (You may not agree with what I say, but it will make you think).
The Compiler never chooses the type for a variable on his own.
If you don't specify a type, it sets the default type, which is LONG.
You can change the default type by using the DefType command
without defining a variable. Like this:
DefType.b
Now each following Variable without a type will be of BYTE type.
So it is always the programmer, that sets the type, even if he doesn't
specify one. The compiler doesn't *assume* which type would be best.
Timo
If you don't specify a type, it sets the default type, which is LONG.
You can change the default type by using the DefType command
without defining a variable. Like this:
DefType.b
Now each following Variable without a type will be of BYTE type.
So it is always the programmer, that sets the type, even if he doesn't
specify one. The compiler doesn't *assume* which type would be best.
Timo
quidquid Latine dictum sit altum videtur
Type Setting
Thanks for the correction. I haven't delved into PureBASIC enough to know these things -- after your first few languages, you then to just try to wing it with each new one, rather than really sit down with the manual. After your first few excursions in writing a program, you might then explore it further by manual (if there is one) to round out your knowledge (if the language looks like a good one, worthy of your time and effort).
So far, dispite the lack of any real documentation, I find PureBASIC interesting enough to spend some time with it. As to the pointer out-of-bounds explanation that I came up with, I don't really know if that is the case. it is just one more thing to explore and verity, and I just advanced that as a possibility that has to be checked for. Because of certain things I read on these forums, I judge that PureBASIC is a thin skin over FASM, and as a consequence, provides a lot of power, but may lack a little on the restraint side when it comes to getting out of bounds. And if there is anything to fear about getting out of bounds, it is the use of pointers!
So far, dispite the lack of any real documentation, I find PureBASIC interesting enough to spend some time with it. As to the pointer out-of-bounds explanation that I came up with, I don't really know if that is the case. it is just one more thing to explore and verity, and I just advanced that as a possibility that has to be checked for. Because of certain things I read on these forums, I judge that PureBASIC is a thin skin over FASM, and as a consequence, provides a lot of power, but may lack a little on the restraint side when it comes to getting out of bounds. And if there is anything to fear about getting out of bounds, it is the use of pointers!
has-been wanna-be (You may not agree with what I say, but it will make you think).

