String Slicing
Posted: Wed Aug 19, 2026 9:11 am
An important optimization that is a little counter intuitive is PAWN string slicing, best shown in the following example:
SUMMARY: By passing an indexed array (my_array[5] instead of my_array) into a function or native which accepts an array, the index you pass in becomes the base of the array the function you called accepts.
So, if you pass in my_array[5] to my_func, then when my_func does your_array[0], it is the value of my_array[5].
LONGER EXPLANATION:
To most, this would be assumed to be a compiler error. After all, it looks as if you are simply handing test2 a cell indexed FROM the string, not a string itself!
This is a primitive form of "array slicing", which can be done with any kind of array. It lets you cut out a subset of the array by telling where you want the array to start at when you pass it. True array slicing can do a lot more, but this is the same amount that C affords us natively using pointers, so we can't be picky.
USES:
Why is this useful? Well, for one thing, it can allow us to do a lot of operations without calls to natives. For example, usually when you want a subset of the string, you have to use copyc or format to get it out, therefore using a native call AND allocating a buffer onto the stack (costly due to zeroing).
However, what if you don't REALLY want a new copy; it'd be perfectly fine if the old copy was messed with and mangled, you just don't want the front part? Or, what if you aren't even going to edit the string; you just need to cut a part out? In that case, string slicing is the only real way to do it, unless you want to go to costly natives like format. Here is a peice of code which makes this easy to understand:
We still use a str function: containi. However, to do stuff in "parse" normally, we'd have to pass in i, and do all offsets based on i. This is extremely cost ineffecient, ugly to look at, and hard to understand (and thus error prone). The string slicing method is a lot cleaner.
Obviously, there are better examples; for instance, the one I am quite fond of is for using in set_task. Instead of using explode (costly) or strtok (costly), if we assume we don't really need nor care about keeping the integrity of the string (which is almost always the case; you use parts of the string, then you don't use them again, therefore you can ruinate them all you want) then the string slicing alternative becomes a lot more cost efficient.
Another example is when you wish to stuff non-string data at the beginning of a string, for space or efficiency reasons. In some of my newer code, it is often the case that stuffing a few integer values at the beginning of a string is more portable than enum based structs, and a lot simpler to understand in code; what was perhaps 4 integers and a string being passed into another plugin, saved somewhere, only to be passed back without ever being parsed, is now one array. Quite a lot easier on the eyes.
A full explanation of how string slicing works is attached to this post, if you care to read it; I do not guarantee its validity, as it is quite early in the morning.
SUMMARY: By passing an indexed array (my_array[5] instead of my_array) into a function or native which accepts an array, the index you pass in becomes the base of the array the function you called accepts.
So, if you pass in my_array[5] to my_func, then when my_func does your_array[0], it is the value of my_array[5].
LONGER EXPLANATION:
Code: Select all
public test()
{
new str2[100] = "y halo thar"
test2(str2[2]);
}
// This shows that its not a fluke or a compiler optimization
public test2(str[])
{
test3(str)
}
public test3(str[])
{
// Writes "halo thar" to file
write_file("addons/amxmodx/test.ini",str);
}This is a primitive form of "array slicing", which can be done with any kind of array. It lets you cut out a subset of the array by telling where you want the array to start at when you pass it. True array slicing can do a lot more, but this is the same amount that C affords us natively using pointers, so we can't be picky.
USES:
Why is this useful? Well, for one thing, it can allow us to do a lot of operations without calls to natives. For example, usually when you want a subset of the string, you have to use copyc or format to get it out, therefore using a native call AND allocating a buffer onto the stack (costly due to zeroing).
However, what if you don't REALLY want a new copy; it'd be perfectly fine if the old copy was messed with and mangled, you just don't want the front part? Or, what if you aren't even going to edit the string; you just need to cut a part out? In that case, string slicing is the only real way to do it, unless you want to go to costly natives like format. Here is a peice of code which makes this easy to understand:
Code: Select all
new str_to_cut[] = "Cut us here| Woah important info"
stock testfunc(str[])
{
new i = containi(str,"|")
parse_me(str[i])
}
stock parse_me(str[])
{
// Do stuff on string AFTER pipe
}Obviously, there are better examples; for instance, the one I am quite fond of is for using in set_task. Instead of using explode (costly) or strtok (costly), if we assume we don't really need nor care about keeping the integrity of the string (which is almost always the case; you use parts of the string, then you don't use them again, therefore you can ruinate them all you want) then the string slicing alternative becomes a lot more cost efficient.
Another example is when you wish to stuff non-string data at the beginning of a string, for space or efficiency reasons. In some of my newer code, it is often the case that stuffing a few integer values at the beginning of a string is more portable than enum based structs, and a lot simpler to understand in code; what was perhaps 4 integers and a string being passed into another plugin, saved somewhere, only to be passed back without ever being parsed, is now one array. Quite a lot easier on the eyes.
A full explanation of how string slicing works is attached to this post, if you care to read it; I do not guarantee its validity, as it is quite early in the morning.