Page 1 of 1
Can a pointer be a negative number?
Posted: Sun Apr 20, 2025 5:43 pm
by AZJIO
I would like to set a negative number when returning a pointer from a procedure on errors. Can I do that? I found no mention of this in the
reference file.
The point is that if we interpret the pointer as a number, the high bit may be considered as a negative value of the number.
If there is no error I should get the actual pointer to use in the following functions.
Code: Select all
Procedure FuncName()
Protected *m
If x
ProcedureReturn -1
EndIf
If y
ProcedureReturn -2
EndIf
If z
ProcedureReturn -3
EndIf
ProcedureReturn *m
EndProcedure
*m = FuncName()
If *m < 0
Debug "Error"
Select *m
Case -1
Debug "Error=1"
Case -2
Debug "Error=2"
Case -3
Debug "Error=3"
Default
; ...
EndSelect
EndIf
Re: Can a pointer be a negative number?
Posted: Sun Apr 20, 2025 6:26 pm
by mk-soft
Maybe works, but I think it's programmed for unclean
Code: Select all
Prototype Invoke()
Procedure Func1()
Debug "Function 1"
EndProcedure
Procedure Func2()
Debug "Function 2"
EndProcedure
Procedure FuncName(Name.s, *Func.Integer)
Protected *m
If Not *Func
ProcedureReturn -1
EndIf
If x
ProcedureReturn -2
EndIf
If y
ProcedureReturn -3
EndIf
If z
ProcedureReturn -4
EndIf
;
Select Name
Case "1"
*Func\i = @Func1()
Case "2"
*Func\i = @Func2()
Default
ProcedureReturn -5
EndSelect
ProcedureReturn 0 ; Ok
EndProcedure
Define function.Invoke
r1 = FuncName("2", @function)
If r1
Debug "Error=" + r1
Else
function()
EndIf
Re: Can a pointer be a negative number?
Posted: Sun Apr 20, 2025 6:50 pm
by NicTheQuick
Usually pointers are unsigned values. but depending on the programming language and available data types you can interpret them as negative values. Because of ASLR (Address Space Layout Randomization) you can in fact get negative values although you only use very less memory in your application.
But you can usually hide 2 bits in pointers if you assume that the pointers are always aligned. As you can see in this example the two lowest bits are always zero.
Code: Select all
Define s.s = "hi"
Define *p = AllocateMemory(4)
Procedure hi()
EndProcedure
DataSection
hi:
Data.i 0
EndDataSection
Debug Bin(@s)
Debug Bin(*p)
Debug Bin(@hi())
Debug Bin(?hi)
Okay, that's still a hack and maybe does not help you. So here's the best solution: Just use another parameter for additional return values of a function.
Code: Select all
Procedure FuncName(*ptr.Integer)
Protected *m
If Not *ptr
ProcedureReturn 1
EndIf
If x
ProcedureReturn 2
EndIf
If y
ProcedureReturn 3
EndIf
If z
ProcedureReturn 4
EndIf
*ptr\i = *m
ProcedureReturn 0
EndProcedure
Define *m
error = FuncName(@*m)
If error
Debug "Error"
Select error
Case 1
Debug "Invalid argument"
Case 2
Debug "Error=2"
Case 3
Debug "Error=3"
Case 4
Debug "Error=4"
Default
; ...
EndSelect
EndIf
Re: Can a pointer be a negative number?
Posted: Sun Apr 20, 2025 7:00 pm
by mk-soft
With macOS I have already seen odd functions addresses!
Re: Can a pointer be a negative number?
Posted: Sun Apr 20, 2025 7:10 pm
by AZJIO
Then the old-fashioned analog of GetLastError()
Code: Select all
Global g_LastError
Procedure FuncName()
Protected *m
g_LastError = 0
If x
g_LastError = 1
ProcedureReturn 0
EndIf
If y
g_LastError = 2
ProcedureReturn 0
EndIf
If z
g_LastError = 3
ProcedureReturn 0
EndIf
ProcedureReturn *m
EndProcedure
*m = FuncName()
If g_LastError
Debug "Error"
Select g_LastError
Case 1
Debug "Error=1"
Case 2
Debug "Error=2"
Case 3
Debug "Error=3"
EndSelect
Else
Debug *m
EndIf
Re: Can a pointer be a negative number?
Posted: Sun Apr 20, 2025 7:20 pm
by NicTheQuick
AZJIO wrote: Sun Apr 20, 2025 7:10 pm
Then the old-fashioned analog of GetLastError()
Code: Select all
Global g_LastError
Procedure FuncName()
Protected *m
g_LastError = 0
If x
g_LastError = 1
ProcedureReturn 0
EndIf
If y
g_LastError = 2
ProcedureReturn 0
EndIf
If z
g_LastError = 3
ProcedureReturn 0
EndIf
ProcedureReturn *m
EndProcedure
*m = FuncName()
If g_LastError
Debug "Error"
Select g_LastError
Case 1
Debug "Error=1"
Case 2
Debug "Error=2"
Case 3
Debug "Error=3"
EndSelect
Else
Debug *m
EndIf
...and if you want to have it Threadsafe you can just use `Threaded` instead of `Global`, which is also automatically global and it will result in one version of `g_LastError` per Thread.
Re: Can a pointer be a negative number?
Posted: Sun Apr 20, 2025 7:25 pm
by AZJIO
I realized that if a number does not support negative numbers, then it will not take this form, for example:
So my question was bound to fail.
Re: Can a pointer be a negative number?
Posted: Sun Apr 20, 2025 11:28 pm
by Demivec
In PureBasic a pointer represents an unsigned address value but it is represented by a signed integer. This means the value can be negative.
You can select a special value or range of values to use as an error indicator. The value -1 can be used as a singular error indicator because its unsigned value is the highest possible memory location. You couldn't store more than a byte there so it wouldn't be the address of a structure, buffer, or procedure. Address zero is likewise a good error indicator.
Re: Can a pointer be a negative number?
Posted: Tue Apr 22, 2025 8:27 am
by Olli
(4-bits convention)
-> Signed value 0x0Fh will give -1
-> Unsigned value 0x0Fh will give 15
Pointer is an unsigned value : everything is positive, whatever the status of the most significant binary digit.
My suggest :
Code: Select all
Procedure exception1()
EndProcedure
Procedure exception2()
EndProcedure
Procedure exception3()
EndProcedure
Procedure exception4()
EndProcedure
Procedure FuncName()
Protected *m
If x
ProcedureReturn @exception1()
EndIf
If y
ProcedureReturn @exception2()
EndIf
If z
ProcedureReturn @exception3()
EndIf
ProcedureReturn *m
EndProcedure
*m = FuncName()
If *m < 0
Debug "Error"
Select *m
Case @exception1()
Debug "Error=1"
Case @exception2()
Debug "Error=2"
Case @exception3()
Debug "Error=3"
Default
; ...
EndSelect
EndIf
Re: Can a pointer be a negative number?
Posted: Tue Apr 22, 2025 2:02 pm
by ricardo_sdl
For pointers I always return #Null when something went wrong or it wasn't possible to return a valid pointer. If I need to know what what happenened I add an output parameter like this:
Code: Select all
Procedure GetFunc(Name.s, *ReturnError.Long)
If Name = "name1"
ProcedureReturn *p1
ElseIf Name = "name2"
ProcedureReturn *p2
EndIf
If error1
*ReturnError\l = -1
Else
*ReturnError\l = -2
EndIf
ProcedureReturn #Null
EndProcedure
And then I call like this:
Code: Select all
Define Name.s = "invalid"
Define ReturnError.Long
Define *Func = GetFunc(Name, @ReturnError)
If *Func = #Null
Debug ReturnError\l
EndIf