- Регистрация
- 28 Сен 2013
- Сообщения
- 752
- Лучшие ответы
- 4
- Репутация
- 166
Автор перевода: Daniel_Cortez
Оригинальный текст: github.com/pawn-lang/compiler/wiki/Const-Correctness
Оригинальный текст: github.com/pawn-lang/compiler/wiki/Const-Correctness
В компиляторе, начиная с версии 3.10.9, появилось новое предупреждение, относящееся к правильному использованию const в объявлениях и реализациях функций.
PHP:
warning 239: literal array/string passed to a non-const parameter
Цель данной статьи - объяснить, что такое const-корректность, зачем она нужна и как можно писать код лучше.
Передача аргументов
Перед тем как разобраться, что означает const в объявлениях/реализациях функций, следует хорошо понимать, какими способами аргументы могут передаваться в функцию
Передача по значению
Когда вы передаёте в функцию обычные переменные, они передаются по значению:
PHP:
main() {
new a; // Переменная 'a' создаётся здесь.
f(a); // 'a' передаётся в функцию 'f' по значению.
}
f(b) {
// 'b' - это копия 'a'.
// При изменении значения в 'b' значение 'a' не изменится.
}
Передача по ссылке
Также можно добавить амперсанд (знак "&") перед названием аргумента, чтобы указать компилятору, что аргумент передаётся по ссылке:
PHP:
main() {
new a; // Переменная 'a' создаётся здесь.
f(a); // 'a' передаётся в функцию 'f' по ссылке.
// Поскольку 'f' модифицирует аргумент,
// переменная 'a' теперь равна трём.
}
f(&b) {
// 'b' - это ссылка на 'a'.
// Изменив значение 'b' мы изменим его и в 'a'.
b = 3;
}
Массивы и передача по ссылке
Массивы всегда передаются по ссылке. Причина этого не охватывается данным уроком, но вы можете почитать, почему так сделано в языке C - то же самое применимо и к Pawn.
Именно поэтому в SA-MP работают такие функции, как например GetPlayerName - они принимают ссылку на массив, который достаточно большой, чтобы вместить никнейм игрока, и записывает никнейм в массив. Ей не нужно возвращать никнейм, потому что она просто модифицирует указанный ей массив.
PHP:
main() {
new a[4];
GetHi(a);
// В 'a' теперь записано "hi!" с символом конца строки.
}
GetHi(input[]) {
input[0] = 'h';
input[1] = 'i';
input[2] = '!';
input[3] = '\0';
}
PHP:
main() {
GetHi("123");
}
GetHi(input[]) {
input[0] = 'h';
input[1] = 'i';
input[2] = '!';
input[3] = '\0';
}
Семантика const
И здесь на помощь приходит const. Стоит отметить, что это далеко не новый функционал компилятора; единственное, что здесь новое - это предупреждение, указывающее на функции, которые должны либо использовать const, либо модифицировать передаваемый им массив и этим массивом не должен быть строковый/массивный литерал.
Вот пример функции, которая не модифицирует передаваемый ей массив, а просто выводит его как строку:
PHP:
main() {
Say("Привет!");
}
Say(input[]) {
if(input[0] == '\0') {
return;
}
printf("Я говорю: %s", input);
return;
}
Тем не менее, семантика сигнатуры* функции некорректна. Некорректность можно заметить, просто прочитав сигнатуру функции:
- Функция называется Say.
- Она принимает массив в качестве аргумента.
- Она может модифицировать массив.
Как это исправить? С помощью const!
PHP:
Say(const input[]) {
if(input[0] == '\0') {
return;
}
printf("I say: %s", input);
return;
}
* Сигнатура - комбинация квалификатора функции, типов аргументов, квалификаторов аргументов и типа возвращаемого значения.
Заключение
Надеюсь, этот урок был полезным и вы уже можете найти новые ошибки в своём коде. Может показаться, что компилятор чересчур придирчив, но эти ошибки могут вызвать серьёзные проблемы, причины которых трудно найти (например, ошибки времени выполнения "Invalid instruction").
Вы можете использовать код ниже, дабы "игнорировать" данные предупреждения, добавив его в начало Вашего мода.
PHP:
#pragma warning disable 219
#pragma warning disable 239
#pragma warning disable 214
Последнее редактирование модератором: