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.
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
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.
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.
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
Last edited by NicTheQuick on Sun Apr 20, 2025 7:18 pm, edited 1 time in total.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
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.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
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.
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: