Re: Today I learned - Share your newly found knowledge! -
Darrenr - 15.09.2015
Quote:
Originally Posted by Freezo
Today i learned that when you declare a stock or a function like :
Код:
stock printf.one() { }
The compiler doesn't manage that, well because of the point ' .', and it gives an error of " Undefined symbol", but how can we fix that?
Well its really simple.
- First, we will need to declare a define
- the define will basically replace the real one.
Take a look:
Код:
#define printf. _replace_
Код:
stock printf.one() { }
stock printf.two() { }
stock printf.three() { }
What did i do? Well simply i create a define that replace the printf with _replace_ which the compiler will read it like this:
Код:
stock _replace_one() {}
stock _replace_two() {}
stock _replace_three {}
Done.
Edit: i didn't tough that its something made before: Here
|
does giving a point (like "printf.one") benefit the code? Or isit a naming preference?
Re: Today I learned - Share your newly found knowledge! -
Stanford - 17.09.2015
Quote:
Originally Posted by Darrenr
does giving a point (like "printf.one") benefit the code? Or isit a naming preference?
|
the 'look' is like Object Oriented programming, and about performance I don't think that it will really benefit the code (I somehow thing that it will slow it down abit instead of using normal way) it might benefit you while reading the code.
I hope I helped any feedback is appreciated!
Re: Today I learned - Share your newly found knowledge! -
Slice - 17.09.2015
It does not affect speed in any way, because the replacements are doing during compile-time (not run-time).
I've done this previously:
pawn Код:
#define DB:: DB_
new DB::SomeVariable = 2;
stock DB::Initialize()
{
}
Re: Today I learned - Share your newly found knowledge! -
Slice - 06.10.2015
Today I learned that CallLocalFunction and CallRemoteFunction do in fact support arrays, and it copies the array to the heap of the receiving AMX, so it's safe to use between filterscripts and/or the gamemode.
There is one caveat: you must have an integer argument passed after it, containing the array size.
pawn Код:
new arr[] = {11, 22, 33, 44};
CallRemoteFunction("test", "ai", arr, sizeof(arr));
}
forward test(arr[], arrlen);
public test(arr[], arrlen) {
for (new i = 0; i < arrlen; i++) {
printf("arr[%d] = %d", i, arr[i]);
}
}
Output:
Код:
arr[0] = 11
arr[1] = 22
arr[2] = 33
arr[3] = 44
Re: Today I learned - Share your newly found knowledge! -
Crayder - 06.10.2015
Quote:
Originally Posted by Slice
Today I learned that CallLocalFunction and CallRemoteFunction do in fact support arrays, and it copies the array to the heap of the receiving AMX, so it's safe to use between filterscripts and/or the gamemode.
There is one caveat: you must have an integer argument passed after it, containing the array size.
pawn Код:
new arr[] = {11, 22, 33, 44}; CallRemoteFunction("test", "ai", arr, sizeof(arr)); }
forward test(arr[], arrlen); public test(arr[], arrlen) { for (new i = 0; i < arrlen; i++) { printf("arr[%d] = %d", i, arr[i]); } }
Output:
Код:
arr[0] = 11
arr[1] = 22
arr[2] = 33
arr[3] = 44
|
Think of it like you're passing a string. A string is an array of integer key codes (which are integers). An 'array' is an array of integers. After looking at it like that and knowing that you can pass strings then it's kind of obvious.
Re: Today I learned - Share your newly found knowledge! -
Slice - 06.10.2015
Integer key codes? What.
Either way, "cells" is the correct term when you talk about the abstract representation of a value in AMX memory. An integer is a cell with an empty tag. A float is a cell with the Float tag.
Passing an array is different from passing a string. If a string is sent from an array of size 128, but the string length is 10, then only 11 cells will be given to the callee.
Also, characters range from 0-255. Any bits above the 8th will be lost.
Re: Today I learned - Share your newly found knowledge! -
Jaxson - 06.10.2015
Today I learned that GetPlayerKeys doesn't work in OnPlayerDialogResponse callback.
Re: Today I learned - Share your newly found knowledge! -
Crayder - 06.10.2015
Quote:
Originally Posted by Slice
Integer key codes? What.
Either way, "cells" is the correct term when you talk about the abstract representation of a value in AMX memory. An integer is a cell with an empty tag. A float is a cell with the Float tag.
Passing an array is different from passing a string. If a string is sent from an array of size 128, but the string length is 10, then only 11 cells will be given to the callee.
Also, characters range from 0-255. Any bits above the 8th will be lost.
|
This is pawn, a string is literally an array of characters. The characters are stored as integers. Unless you specifically tell the script to make a char array it will be treated as any other array.
Re: Today I learned - Share your newly found knowledge! -
Slice - 06.10.2015
I'm talking about CallRemoteFunction, and how strings/arrays are treated there. Not sure what you're on about..
There is no way for CallRemoteFunction to know the array size of a string, because it's not given to it; he only thing it knows is the string length. It allocates L+1 cells on the receiving AMX -
not the size of the array holding the string.
A char array is no different from any other array. The "char" keyword is the exact same thing as doing a ceildiv by 4. The {n} subscript is to read/write each byte of an array, as opposed to each cell.
pawn Код:
new arr[1] = {0xAABBCCDD};
printf("%x, %x, %x, %x", arr{0}, arr{1}, arr{2}, arr{3});
new arr2[20 char] = {1, 2, ...};
for (new i = 0; i < sizeof(arr2); i++) printf("%d", arr2[i]);
Woo. Magic.
Re: Today I learned - Share your newly found knowledge! -
Crayder - 06.10.2015
Quote:
Originally Posted by Slice
I'm talking about CallRemoteFunction, and how strings/arrays are treated there. Not sure what you're on about..
There is no way for CallRemoteFunction to know the array size of a string, because it's not given to it; he only thing it knows is the string length. It allocates L+1 cells on the receiving AMX - not the size of the array holding the string.
A char array is no different from any other array. The "char" keyword is the exact same thing as doing a ceildiv by 4. The {n} subscript is to read/write each byte of an array, as opposed to each cell.
pawn Код:
new arr[1] = {0xAABBCCDD}; printf("%x, %x, %x, %x", arr{0}, arr{1}, arr{2}, arr{3}); new arr2[20 char] = {1, 2, ...}; for (new i = 0; i < sizeof(arr2); i++) printf("%d", arr2[i]);
Woo. Magic.
|
My point is that if strings could be passed to CallRemote/LocalFunction, so can arrays.
Re: Today I learned - Share your newly found knowledge! -
Slice - 06.10.2015
Oh my bad, I thought you wanted to actually discuss the technical details. You just wanted to tell the world what you think.
Maybe we can start putting 2d arrays into them also? With your logic, it should work just fine!
Cool, another feature discovered by the power of ignorance!
Sarcasm aside, 2d arrays are doable but sizeof won't suffice for the size calculation.
Re: Today I learned - Share your newly found knowledge! -
Crayder - 25.10.2015
printf iterates through it's parameters in reverse.
Re: Today I learned - Share your newly found knowledge! -
ThePhenix - 31.10.2015
Today I learned that you can have concurrent operations using the comma operator.
Код:
new i, j;
j = 0;
i = (j++, j+=1, j+=1, j *= 2, j /= 10, j += 15, j * 2);
Which outputs 30 for as the value stored in "i".
Re: Today I learned - Share your newly found knowledge! -
Slice - 01.11.2015
Quote:
Originally Posted by Crayder
printf iterates through it's parameters in reverse.
|
its*
A function doesn't iterate through its parameters; they are pushed onto the stack in reverse order.
PUSH c
PUSH b
PUSH a
The frame now looks like this:
12+8 - c
12+4 - b
12+0 - a
12 - arg count
8 - return addr
4 - ??
0 - return pos
If you look at the assembly output, you will see why it makes sense to do it that way.
Quote:
Originally Posted by ThePhenix
Today I learned that you can have concurrent operations using the comma operator.
Код:
new i, j;
j = 0;
i = (j++, j+=1, j+=1, j *= 2, j /= 10, j += 15, j * 2);
Which outputs 30 for as the value stored in "i".
|
They're not concurrent (that would be crazy!). You can also do if/and/or/else without an if-statement.
pawn Код:
a && (a = 0) || (b = 1)
// translation:
if (a) {
a = 0;
} else {
b = 1;
}
a && (a = 0, b) && (b = 0, c) && (c = 0, d) && (d = 0)
// translation:
if (a) {
a = 0;
if (b) {
b = 0;
if (c) {
c = 0;
if (d) {
d = 0;
}
}
}
}
Re: Today I learned - Share your newly found knowledge! -
Crayder - 01.11.2015
Quote:
Originally Posted by Slice
If you look at the assembly output, you will see why it makes sense to do it that way.
|
I did look at the assembly, that's how I figured it out in the first place.
Re: Today I learned - Share your newly found knowledge! -
Ahmad45123 - 03.12.2015
Quote:
Originally Posted by Patrick
I learned this quite a while ago but its worth something sharing. This will avoid you from repeating the code over and over again. Repeating dialogs could be annoying sometimes because you'll have to change everything that you've repeated.
pawn Код:
JustATestFunc(playerid, randomValue, higherValue) { if(playerid == INVALID_PLAYER_ID) { goto RandomDialog; return 1; } if(randomValue < 10 || higherValue > 1000) { goto RandomDialog; return 1; }
RandomDialog: ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Example", "Example", "Yes", "No"); return 1; }
Instead of
pawn Код:
JustATestFunc(playerid, randomValue, higherValue) { if(playerid == INVALID_PLAYER_ID) { ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Example", "Example", "Yes", "No"); return 1; } if(randomValue < 10 || higherValue > 1000) { ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Example", "Example", "Yes", "No"); return 1; }
RandomDialog: ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Example", "EXample", "Yes", "No"); return 1; }
|
Or, Here is how I'd do it:
PHP код:
JustATestFunc(playerid, randomValue, higherValue)
{
//Make sure everything is correct.
if(playerid != INVALID_PLAYER_ID) return 1;
if(randomValue > 10 && higherValue < 1000) return 1;
//Show the dialog.
ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Example", "Example", "Yes", "No");
return 1;
}
Also btw, the line about INVALID_PLAYER_ID should be the opposite but seeing as its only a test function, no problem :P
Re: Today I learned - Share your newly found knowledge! -
Vince - 03.12.2015
Quote:
Originally Posted by Patrick
I learned this quite a while ago but its worth something sharing. This will avoid you from repeating the code over and over again. Repeating dialogs could be annoying sometimes because you'll have to change everything that you've repeated.
|
Every self-respecting programmer will tell you that goto must
never be used. It inevitably leads to spaghetti code and there are
always better ways to solve it. To avoid "repeating the code over and over again", as you so nicely put it, functions were invented.
Re: Today I learned - Share your newly found knowledge! -
Slice - 03.12.2015
Quote:
Originally Posted by Vince
Every self-respecting programmer will tell you that goto must never be used. It inevitably leads to spaghetti code and there are always better ways to solve it. To avoid "repeating the code over and over again", as you so nicely put it, functions were invented.
|
There are cases where it actually is a bit useful, but it's rare. In his example, he could just have refactored the if statements.
One place where goto is useful is obviously when dealing with #emit, but another place could be if you want to make a C-like switch statement with fall-through.
I've used it in
strlib without feeling too bad about it, as well as
here.
That said, always try to do what you do without using goto! It can cause undefined behavior and confusion..
For example, have a look at my goto usage in strlib
here. I use "goto return_false" before the variable "ret" is instantiated - madness?!?!
goto modifies the FRM and stack. If you don't know what all these things mean, don't use it!
Re: Today I learned - Share your newly found knowledge! - Patrick - 03.12.2015
Quote:
Originally Posted by Vince
Every self-respecting programmer will tell you that goto must never be used. It inevitably leads to spaghetti code and there are always better ways to solve it. To avoid "repeating the code over and over again", as you so nicely put it, functions were invented.
|
There's nothing wrong with using goto as long as its used correctly and you won't abuse the function because it just looks cooler and looks harder to read. You can always avoid spaghetti code, if you know what you're doing then you won't get a spaghetti code. You can always use functions + goto at the same time but I don't known if there's difference between functions + repetitive ShowPlayerDialog or functions + goto and 1 ShowPlayerDialog.
ps I am typing on my phone, sorry if there's a sentence that doesn't make sense.
Re: Today I learned - Share your newly found knowledge! -
TwinkiDaBoss - 07.12.2015
Today I learned that no matter how many times I leave my command line to print an error for hours, it wont go away.