[Include] pointers.inc - Pointers for PAWN!
#21

Quote:
Originally Posted by Stewie`
Посмотреть сообщение
Thanks for that, but I still don't understand, considering that I lost interest in learning about coding(overall).
Reply
#22

Pointers are a type of variable that points to another variable. With that, we can save alot of memory and make our job way easier like:

pawn Код:
int make_a_zero(int *var)
{
     *var = 0;
     return 0;
}
main()
{
     int hey = 1212;
     make_a_zero(&hey);
}
So hey's value and whatever you put as an argument (int) will become zero.
Reply
#23

Quote:
Originally Posted by Stewie`
Посмотреть сообщение
Pointers are a type of variable that points to another variable. With that, we can save alot of memory and make our job way easier like:

pawn Код:
int make_a_zero(int *var)
{
     *var = 0;
     return 0;
}
main()
{
     int hey = 1212;
     make_a_zero(&hey);
}
So hey's value and whatever you put as an argument (int) will become zero.
Wow. So cool. But that example still doesn't explain how pointers are useful in SA-MP, because it can be translated to PAWN like this:
pawn Код:
stock make_a_zero(&var)
{
     var = 0;
     return 0;
}
main()
{
     new hey = 1212;
     make_a_zero(hey);
}
Reply
#24

Well the example in the first post is one.. Another thing you could do is save the addresses of variables for later use. For examples on what I mean, see stmt_bind_result_field in SQLite Improved and BindUserVar in users.inc (note that I didn't use this library for that, but it's fully doable with it).
Reply
#25

їReally? nice inc Sicle .
Reply
#26

Quote:
Originally Posted by ******
Посмотреть сообщение
There's a fairly major bug in this version. Currently you're doing "idx = idx + 1 & max;" to get the next index to store in. A very common use case is to set up a load of permanent resources (in this case pointers) at the start of the mode (which would result in them being at the start of the array), and then assign and release more temporary pointers as the mode goes. With your current code this will destroy the initial pointers after a while, but I have no idea for a solution (and I suspect you knew this already so I'm not sure why I'm posting).
The only reason I put index in the first place was so it wouldn't get messed up when using multiple pointers in one function call, though I suspect that's not needed when I come to think about it.
Pointer variables hold the absolute address to another variable, not a pointer index.
This, of course, results in a function call each time a pointer is used, which isn't optimal sometimes. I'm thinking there should be a more static way to create pointers as well, but there are some problems that has to be solved before that's possible.

Edit: After some testing, I've now updated the include to a version without these indexes. Memory usage were now reduced a lot and I increased the max index limit to 1024.

PointerByAddress now consists of only 4 instructions!
Reply
#27

OK, I don't quite get how the write works...
pawn Код:
new
    g_Test[] = {123, 456, 789}
;

public OnGameModeInit() {
    new pointer = GetVariableAddress(g_Test);
   
    // Change the 2nd value
    @[pointer][1] = 444;
   
    // Print out the values
    printf("%d, %d, %d", @[pointer][0], @[pointer][1], @[pointer][2]);
}
You write @[pointer][1] = 444.
But how can this (with your definition of @) write 444 g_Test and replace 456?

//EDiT:
OK, figured out what PointerByAddress does.
It just stores the value of the argument into g_aaiPointers, right?

And then this is used:
@[%1] (PointerByAddress (%1), g_aaiPointers[0][0])
But why the devil is the address stored in g_aaiPointers[0][0] assigned with the actual value when you use @[pointer] = value and not just g_aaiPointers[0][0]?

What kind of sorcery is this?

//EDiT 2: OK, maybe I don't understand at all what PointerByAddress does...
Reply
#28

I would give you a clear explanation as to exactly how and why this works, but that what fun would that be for you!?

Let me just give you this hint:
pawn Код:
// Simple assignment
test[2][5] = 123;

// This does the same thing as the line above
// In fact, this is exactly what the PAWN compiler generates
#emit ADDR.pri  test
#emit ADD.C     8
#emit MOVE.alt
#emit LOAD.I    
#emit ADD
#emit ADD.C     20
#emit MOVE.alt
#emit CONST.pri 123
#emit STOR.I
Reply
#29

Tell me only one more thing:

Is this natural behaviour which would be except by everyone familiar with assembly or is this about exploiting a bug?

Because when I do (something(), var[0][0]) = 123;
I expect that var[0][0] is assigned with 123 and not the address it points to.
Same with SomeGlobalVar = (somethingelse(), anothervar[0][0]) where SomeGlobalVar should be assigned with anothervar[0][0] and not with the value which anothervar points to.

//EDiT:
Have you ever thought of make some malloc() and free() functions?
This might be greater combined with your pointers.
Reply
#30

Awesome work Slice ofc as always
Reply
#31

I've released an updated version that adds proper support for multi-dimensional arrays in @ptr. Download at first page.

The rule of thumb here is when using @ptr for arrays with more than 1 dimension, the first dimension has to be inside @ptr[].

Example:
pawn Код:
new array[100][100];

main() {
    new address = GetVariableAddress(array);

    // WRONG:
    @ptr[address][5][10] = 20;
   
    // CORRECT (new):
    @ptr[address, 5, 10] = 20;

    // Also CORRECT:
    @ptr[address, 5][10] = 20;
}
Reply
#32

Just noticed this include, nice one!
Reply
#33

Here's an interesting little experiment with custom operators allowing you to do this:
pawn Код:
new variable = 200;
new Pointer:ptr = PointerToVar(variable);

ptr = 123;

printf("%d", variable);
// Output: 123
Note, though, this only works for assignments. Other things like ++, --, /, * doesn't work. Though they could be added just as easy.

Source:
pawn Код:
// Operator called when an untagged variable is assigned to a value tagged with Pointer
stock Pointer:operator=(value) {
    static addr;
   
    // Get return address
    #emit LOAD.S.alt 4
   
    // Add COD
    #emit LCTRL     0
    #emit ADD
    #emit MOVE.alt
   
    // Subtract DAT
    #emit LCTRL     1
    #emit SUB.alt
   
    // Read the first opcode's parameter
    #emit ADD.C     4
    #emit STOR.pri  addr
    #emit LREF.pri  addr
    #emit STOR.pri  addr
   
    // Is this address relative to the previous frame?
    if (addr <= 0) {
        // Add the previous frame to make it absolute
        #emit LOAD.S.pri  0
        #emit LOAD.alt    addr
        #emit ADD
       
        // Load it and store it
        #emit LOAD.I
        #emit STOR.pri    addr
    } else {
        // Load it and store it
        #emit LOAD.pri  addr
        #emit LOAD.I
        #emit STOR.pri  addr
    }
   
    // Store the new value there
    if (addr) {
        #emit LOAD.S.pri  value
        #emit LOAD.alt    addr
        #emit STOR.I
    }
   
    // Add 8 to the return address (to skip the assignment)
    #emit LOAD.S.pri 4
    #emit ADD.C      8
    #emit STOR.S.pri 4
   
    // Return the same value the pointer was
    return Pointer:0;
}


stock Pointer:PointerToVar(...) {
    #emit LOAD.S.pri  12
    #emit RETN
   
    return Pointer:0;
}
Reply
#34

That's great
Reply
#35

awesome work love it
Reply
#36

My god pointers in PAWN i couldnt resist to post. Damn sexy thanks for the release bro!
Reply
#37

Sorry for bump, but have any possible to get the tag of variable, or argument by similar of this? using emit maybe...

Really sorry for bump, but nice include ^^
Reply
#38

Quote:
Originally Posted by Day_
Посмотреть сообщение
Sorry for bump, but have any possible to get the tag of variable, or argument by similar of this? using emit maybe...

Really sorry for bump, but nice include ^^
Only as a function argument:
pawn Код:
stock SomeFunc({ _, Float, hex}:var, tag = tagof(var))
{
    if (tag == tagof(Float:)) {
        // "var" is a float
    }
}
Reply
#39

Yes, but not in the situation, in a following:
PHP код:
SomeFunc(playeridGLOBAL_TAG_TYPES:...)
{
   if(
tagof(@arg[1]) == tagof(Float:)){ // 0x43
   
}

But the variable in pointers.inc is created with no tag.

But I can possible using the macro.
PHP код:
#define SomeFunc(%0,%1) _SomeFunc(%0,tagof(%1),%1)
_SomeFunc(playeridtagGLOBAL_TAG_TYPES:...)
{
   if(
tagof(tag) == tagof(Float:)){ // 0x43
   
}

I wanted to know if there is another way.

PS: Sorry if not get express better. My english is not fluent
Reply
#40

Quote:
Originally Posted by Day_
Посмотреть сообщение
Sorry for bump, but have any possible to get the tag of variable, or argument by similar of this? using emit maybe...

Really sorry for bump, but nice include ^^
tagof?

https://sampwiki.blast.hk/wiki/Keywords:Operators#tagof

Shit, the forums didn't take me to the last page. I'm late here.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)