Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 5 из 5
  1. #1
    Аватар для Leogin
    Пользователь

    Статус
    Оффлайн
    Регистрация
    07.06.2022
    Сообщений
    13
    Репутация:
    1 ±

    Записать переменную в массив (enum)

    Здраствуйте. Подскажите как решить проблему, допусти есть массив:
    Код HTML:
    enum e_Name {
    	Nick[MAX_PLAYER_NAME + 1],
    	Level,
    };
    
    new
    	Name[4][e_Name] = {
    	{"бета тест", 18},
    	{"тест", 8},
    	{"бета тест", 3},
    	{"бета тест", 1}
    };

    Хочу сделать так:
    Код HTML:
    new
    	BETATEST1[] = "бета тест",
    	TEST1[] = "тест";
    
    enum e_Name {
    	Nick[MAX_PLAYER_NAME + 1],
    	Level,
    };
    
    new
    	Name[4][e_Name] = {
    	{BETATEST1, 18}, // error 008: must be a constant expression; assumed zero
    	{TEST1, 8},
    	{BETATEST1, 3},
    	{BETATEST1, 1}
    }; // error 010: invalid function or declaration
    warning 203: symbol is never used: ""

  2. #2
    Аватар для punkochel
    Пользователь

    Статус
    Оффлайн
    Регистрация
    08.12.2018
    Адрес
    Россия
    Сообщений
    146
    Репутация:
    25 ±
    Дело в том, что в инициализации переменных/массива переменных значениями для них могут служить исключительно константы.
    В твоем случае необходимо использовать функции strmid/strcat/format.

    Я конечно не особо разбирался как работает компилятор pawn, но даже если объявить переменную с параметром const, то использование её в инициализации так-же не предоставляется возможным. Поэтому константы лучше объявлять директивой #define, если они будут использоваться при инициализации. То есть в pawn, на сколько мне известно, константы времени компиляции можно объявить только препроцессорной директивой.
    Тут получается что никакого линкера и в помине нет, и компилирование проходит в 2 этапа: 1 - подставляются все значения директив препроцессора; 2 - непосредственно само компилирование.
    Исходя из всего этого, когда ты инициализируешь массив используя значение объявленной переменной, то компилятор попросту не знает ничего о переменных BETATEST1, TEST1.

  3. Пользователь сказал cпасибо:
    Leogin (11.12.2022)
  4. #3
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от punkochel Посмотреть сообщение
    Дело в том, что в инициализации переменных/массива переменных значениями для них могут служить исключительно константы.
    Не совсем, одиночные переменные можно инициализировать какими угодно значениями (из других переменных, от вызова функций и пр.) непосредственно при объявлении:
    1. Return1() return 1;
    2. main()
    3. {
    4. new x = Return1();
    5. new y = x;
    6. return y;
    7. }

    Ограничение касается именно массивов: их можно проинициализировать только строковыми или массивными литералами.
    (На всякий случай разъясню, что такое "литерал" - это непосредственное константное значение: например, 0x0 - это целочисленный литерал, "текст" - это строковый литерал, { 0, 1, 2 } - это массивный литерал. Для сравнения, более часто используемое слово "константа" может означать как константное значение (например, 0xFF), так и именованную константу (например, const EOF = -1).)

    Цитата Сообщение от punkochel Посмотреть сообщение
    Исходя из всего этого, когда ты инициализируешь массив используя значение объявленной переменной, то компилятор попросту не знает ничего о переменных BETATEST1, TEST1.
    Знать-то он о них знает, только сделать с ними ничего не может: инициализация массивов содержимым других массивов непосредственно во время объявления не поддерживается (по крайней мере, пока что).
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  5. 2 пользователя(ей) сказали cпасибо:
    Leogin (11.12.2022) punkochel (11.12.2022)
  6. #4
    Аватар для punkochel
    Пользователь

    Статус
    Оффлайн
    Регистрация
    08.12.2018
    Адрес
    Россия
    Сообщений
    146
    Репутация:
    25 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Не совсем, одиночные переменные можно инициализировать какими угодно значениями (из других переменных, от вызова функций и пр.) непосредственно при объявлении:
    1. Return1() return 1;
    2. main()
    3. {
    4. new x = Return1();
    5. new y = x;
    6. return y;
    7. }
    Ну с локальными переменными это другая история, т.к. они создаются при входе в блок.
    Но если мы будем говорить о локальном массиве, то мы не сможем даже указать его размер значением функции, которая возвращает константу:
    1. Return5() return 5;
    2. main()
    3. {
    4. new arr[Return1()];
    5. }

    Хотя, вроде бы что тут такого? Компилятору заранее известно значение которое вернет функция. Тем не менее это ошибка. Пусть у нас нет динамической памяти и функции возвращающие вычисленное значение не имеют места быть в инициализации, т.к. заранее стек расчитать невозможно.

    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    Ограничение касается именно массивов: их можно проинициализировать только строковыми или массивными литералами.
    { 0, 1, 2 } - это массивный литерал
    И тут мы увидим тоже ошибку:
    1. stock Return5() return 5;
    2. main()
    3. {
    4. new arr[] = {Return5(), Return5()};
    5. }

  7. Пользователь сказал cпасибо:
    Leogin (11.12.2022)
  8. #5
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Цитата Сообщение от punkochel Посмотреть сообщение
    Но если мы будем говорить о локальном массиве, то мы не сможем даже указать его размер значением функции, которая возвращает константу:
    1. Return5() return 5;
    2. main()
    3. {
    4. new arr[Return1()];
    5. }

    Хотя, вроде бы что тут такого? Компилятору заранее известно значение которое вернет функция.
    Нет, не известно. В отличие от современных компиляторов для Си-подобных языков, компилятор Pawn не работает с абстрактным синтаксическим древом (Abstract Syntax Tree, AST), поэтому многие трансформации и оптимизации кода для него невозможны. Он просто преобразует исходный код, который ему подан, напрямую в ассемблерный листинг, а затем и в байт-код. К слову, те же диагностики warning 240 и warning 252 были бы гораздо проще в реализации при использовании AST; без этого пришлось сильно костылить с запоминанием использования каждой переменной на каждом уровне вложенности if/switch/while/do/for/local.

    Цитата Сообщение от punkochel Посмотреть сообщение
    И тут мы увидим тоже ошибку:
    1. stock Return5() return 5;
    2. main()
    3. {
    4. new arr[] = {Return5(), Return5()};
    5. }
    Ну так это же не константное значение, а результат функции, которая помимо возврата результата может совершать другие действия и иметь побочные эффекты (даже если в примере их нет, опять же, компилятор об этом не знает). Чего ещё здесь можно было ожидать?
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  9. 2 пользователя(ей) сказали cпасибо:
    Leogin (19.12.2022) punkochel (18.12.2022)
 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •