PDA

Просмотр полной версии : [Вопрос] Для чего в макросе isnull есть проверка "(((%1[0]) == '\1') && (!(%1[1])))"



Elrmrnt-Kritik
10.06.2018, 13:37
Всем привет. Уже достаточно давно пользуюсь макросом isnull, имеющимся в pawncmd и mdialog. Но вот возник такой вопрос: зачем там стоит проверка, не равна ли первая ячейка единице? Нельзя проверку производить так?

#define isnull(%0) (!%0[0])

И где вообще следует использовать данный выше вариант и тот, что присутствует в том же mdialog?

Спасибо заранее.

VVWVV
10.06.2018, 14:50
Проверка на '\1' существует из-за проблемы с CallLocalFunction и CallRemoteFunction, поскольку при указании пустой строки сервер падает.

Elrmrnt-Kritik
10.06.2018, 18:09
А почему именно '\1'? Не совсем понял...

VVWVV
10.06.2018, 18:13
А почему именно '\1'? Не совсем понял...

Это не является символом и не является нулём, что соответственно подходит для проверки пустой строки.

Elrmrnt-Kritik
10.06.2018, 18:36
А что касается других символов? Например, '\2', '\3'...? Где-то вообще есть список их и значения?

VVWVV
10.06.2018, 18:49
А что касается других символов? Например, '\2', '\3'...? Где-то вообще есть список их и значения?

Как я уже сказал выше, это специальные символ, который обычно не используется скриптерами. Он есть в таблице ASCII (https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html). Все символы до пробела (32) являются специальными символами.

Elrmrnt-Kritik
10.06.2018, 18:55
А почему тогда проверяют лишь на первые два? Проверили бы на первые 32, до пробела как раз.

VVWVV
10.06.2018, 19:07
А почему тогда проверяют лишь на первые два? Проверили бы на первые 32, до пробела как раз.

Когда мы передаём в функцию по средством CallLocalFunction или CallRemoteFunction пустую строку, то сервер из-за этого падает. Поэтому вместо нуля мы отправляет не пустую строку, а строку с двумя символами, чтобы сервер не падал. Далее, в вызываемой нами функции, то есть той, которая указана в CallLocalFunction или CallRemoteFunction в качестве аргумента, мы должны узнать пустая ли строка, либо нет. Чтобы сделать это максимально удобной и без вызова лишних native-функций мы используем данный макрос, который универсален как для обычных строк, так и для проверки пустой строки в CallLocalFunction или CallRemoteFunction.

Тем не менее, если бы мы проверяли всю строку целиком, то мы бы на это потратили больше времени.

Daniel_Cortez
10.06.2018, 19:27
А почему тогда проверяют лишь на первые два? Проверили бы на первые 32, до пробела как раз.
Потому что нет причины, ибо для обхода бага используются только первые два. К тому же, остальные (2..31) могут использоваться в будущем для других костылей.

Elrmrnt-Kritik
10.06.2018, 19:33
Хорошо, а можно пример, при котором сервер упадет, если я буду использовать этот макрос?

#define isnull(%0) (!%0[0])

Daniel_Cortez
10.06.2018, 20:28
Хорошо, а можно пример, при котором сервер упадет, если я буду использовать этот макрос?

#define isnull(%0) (!%0[0])
Вы точно читаете, что вам отвечают? Падение происходит не из-за макроса, а из-за пустой строки в вызове CallLocalFunction:

#include <a_samp>

public SomeFunction(const string[]);
public SomeFunction(const string[])
{
printf("string: \"%s\"");
}

main()
{
CallLocalFunction(!"SomeFunction", !"s", "");
}

Elrmrnt-Kritik
10.06.2018, 23:46
Я прекрасно понимаю что будет при передачи пустой строки. Но в то же время я не понимаю, зачем Вы проверяете, не равен ли символ '\1'. Можно же ограничиться проверкой первого символа на '\0'.

VVWVV
10.06.2018, 23:53
Я прекрасно понимаю что будет при передачи пустой строки. Но в то же время я не понимаю, зачем Вы проверяете, не равен ли символ '\1'. Можно же ограничиться проверкой первого символа на '\0'.

Если бы мы проверяли так, то строка бы не была пустой.


#include <a_samp>

public SomeFunction(const string[]);
public SomeFunction(const string[])
{
if (isnull(string)) {
printf("the passed string is empty.\n");
} else {
printf("the passed string : \n", string);
}
}

main()
{
CallLocalFunction(!"SomeFunction", !"s", "\1");
}

Elrmrnt-Kritik
11.06.2018, 00:12
Все, спасибо, можно закрыть тему :)