变量(Variable)是由用户创建的标识符,其数值在插件运行后才能确定,并且可更改。
1. 全局变量(Global Variable)
new pluginVar; // 当前插件的所有文件中可以访问此变量
static fileVar; // 当前文件中可以访问此变量
public plugin_init(/*函数内(参数列表内)*/)
{
// 函数内
}
2. 局部变量(Local Variable)
public myFunction(param) // 函数参数也是局部变量
{
new localVar1; // 函数内声明的局部变量(临时变量)
static localVar2; // 函数内声明的局部变量(静态变量)
}
按储存位置划分,变量可以分为数据段变量和栈变量。
全局变量和函数体内用static声明的变量属于数据段变量,数据段变量的声明、定义仅在插件启动时执行一次,确定初始值。
函数体内用new关键字声明的是栈变量,栈变量的声明、定义可在插件运行时重复执行,重复计算不同初始值。
参数分为传值和传引用,传值参数是实参的临时副本,必定是栈变量;传引用参数等于实参本体,实参有可能是数据段变量。
关于参数变量的相关概念:点击查看参数指南
非参数变量声明语句语法格式:
变量声明语法拆解:
维度声明语法拆解:
初始化表达式拆解:
注意:
new public static stock 可用于编写全局变量声明语句。
new static 可用于编写局部变量声明语句。
若额外添加 const 关键字进行修饰,可令变量获得只读特性。变量值在初始化之后不能被运算符修改。
代码示例:
// 声明假公共只读变量(数据段变量,全局变量)
public const Float:NULL_VECTOR[3] = { 0.0, 0.0, 0.0 };
// 声明插件私有备用只读变量(数据段变量,全局变量)
stock const Float:V3_4Dir[][] =
{
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ -1.0, 0.0, 0.0 },
{ 0.0, -1.0, 0.0 }
};
// 声明文件私有变量(数据段变量,全局变量)
static m_flNextAttack = 83;
// 声明插件私有变量(数据段变量,全局变量)
new bool:gWeaponShooting;
public plugin_init()
{
// 声明静态只读变量(数据段变量,静态局部变量)
static const PluginName[] = "插件名称";
// 声明临时变量(栈变量,局部变量)
new pluginId = register_plugin(PluginName, "插件版本", "插件作者");
}
若不填写值类型标签,变量将会获得默认标签 _:
因此,下面两行代码是相同的:
new _:variable;
new variable;
若填写未定义的值类型标签,编译器会自动创建这个标签。
当变量与拥有不同标签的表达式做运算时,通常会触发编译器警告:
// variable拥有_标签,表达式15.0拥有Float标签,触发警告:"标签不匹配"
new _:variable = 15.0;
变量通常是用来储存函数返回值或充当函数的参数,因此需要定义与函数或参数相同的标签。
另外,定义不同的值类型标签,会导致变量参与运算时,根据运算符重载触发不同的运算函数。
若这个标签没有运算符重载,将会触发默认的运算函数。
声明变量时,在变量名称末尾添加中括号,会让变量变成数组,使变量可以储存多个数值。
中括号的数量表示数组的维度,[ ][ ]表示变量是2维数组。[ ][ ][ ]表示变量是3维数组。
3维数组储存的元素是多个2维数组,2维数组储存的元素是多个1维数组,1维数组储存的元素是多个数值。
中括号内可填写常量表达式(单值字面量或常量),表示各维度数组的尺寸(元素数量)。
在有多对中括号时,填写的尺寸从左至右对应从外层至内层数组。
代码示例:
// 创建3尺寸的1维数组,他能储存3个值
static array1[3];
// 创建2维数组:2维数组尺寸为3,1维数组尺寸为2
static array2[3][2];
// 创建3维数组:3维数组尺寸为4,2维数组尺寸为3,1维数组尺寸为2
static array3[4][3][2];
若使用枚举结构体名称充当1维数组尺寸,编译器会按照枚举的成员结构,将数组解析为结构体。
此时允许使用枚举成员访问结构体的属性:
enum tZombieClass_Normal
{
_: ZCN_Name[32],
_: ZCN_MaxHealth,
_: ZCN_MaxSpeed,
Float: ZCN_EyePos[3]
}
static sZombieClass[tZombieClass_Normal];
public plugin_init()
{
// 访问ZCN_EyePos常量所指的结构体属性,该属性是3尺寸数组,修改这个数组的值
// AMX Mod X 1.8.3以下版本中,用=运算符会错误解析属性标签为_,因此需以_覆盖右值标签,避免警告
sZombieClass[ZCN_EyePos] = _:{ 0.0, 0.0, 17.0 };
// AMX Mod X 1.8.2以上版本中,可正常解析属性标签,但数组字面量在任何版本中都是_标签,需以Float标签覆盖(在初始化表达式中不检查数组字面量标签,所以不需要)
sZombieClass[ZCN_EyePos] = Float:{ 0.0, 0.0, 17.0 };
}
关于枚举结构体:点击查看enum指南
若省略初始化表达式,则变量储存的每个初始值被设为0。
在为单值变量设置初始值时,若未使用 new 关键字,仅允许填写常量表达式。
#include <float>
/* +的两个操作数都含有Float标签,而且float.inc内含有此定义:
* native Float:operator+(Float:oper1, Float:oper2) = floatadd;
* 因此10.0 + 5.0将会变为floatadd(10.0, 5.0)
* 而static声明的变量并不支持使用函数进行初始化,因此会报错:"必须使用常量表达式" */
static Float:var = 10.0 + 5.0;
在为数组设置初始值时,仅允许填写常量表达式,数组字面量,字符串字面量:
// 使用常量表达式,将数组第一个元素值设为15
static array1[3] = 10 + 5;
// 使用常量表达式,将数组第一个元素值设为15.0
static Float:array2[3] = 15.0;
// 使用数组字面量,对2维数组的每个元素进行初始化
static Float:array3[4][3] =
{
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ -1.0, 0.0, 0.0 },
{ 0.0, -1.0, 0.0 }
};
// 使用字符串字面量,对2维数组的每个元素进行初始化
static array4[4][] =
{
"字符串字面量1",
"字符串字面量2",
"字符串字面量3",
"字符串字面量4"
};
数组字面量或字符串字面量的尺寸可以小于维度声明中设定的尺寸,编译器会自动将空缺的元素值设定为0。
使用常量表达式进行初始化与此类似,只能对数组第一个数值元素赋值,后续数值元素皆为0。
编译器提供了2种自动推测后续元素值的写法:
// 每个1维数组拥有8个数值
static array[2][8] =
{
// 后续7个数值皆等于1
{ 1, ... },
// 用4-0得到差值4,后面每个数值都等于上一个数值+4,即{ 5, 0, 4, 8, 12, 16, 20, 24 }
{ 5, 0, 4, ... }
};
若维度声明中未填写尺寸,编译器会根据初始化表达式自动推测尺寸,此时禁止使用 ... 运算符。
// 尺寸=1
static array1[] = 10 + 5;
// 尺寸=3
static Float:array2[] = { 15.0, 15.0, 15.0 };
// 2维数组尺寸=4,1维数组尺寸=3
static Float:array3[][] =
{
{ 1.0, 0.0, 0.0 },
{ 0.0, 1.0, 0.0 },
{ -1.0, 0.0, 0.0 },
{ 0.0, -1.0, 0.0 }
};
若使用枚举结构体名称充当1维数组尺寸,编译器会按照枚举的成员结构,将数组解析为结构体。
此时允许使用结构体字面量进行初始化:
enum tZombieClass_Normal
{
_: ZCN_Name[32],
_: ZCN_MaxHealth,
_: ZCN_MaxSpeed,
Float: ZCN_EyePos[3]
}
static sZombieClass[tZombieClass_Normal] = { "普通僵尸", 1000, 240, { 0.0, 0.0, 34.0 } };
关于枚举结构体:点击查看enum指南
与常量声明语句不同,变量声明语句允许连续声明多个变量:
new var1, bool:var3 = true, Float:var3 = 5.0;
提示:连续声明的变量不能更换声明说明符,因此它们获得的特性是相同的。
数据段变量的声明语句仅在插件启动(载入游戏地图)时执行一次。
意味着下一次来到声明语句位置,并不会重新初始化,而是保持上次修改的数值。
#include <amxmodx>
public plugin_init()
{
test(); // 第1次进入函数内部执行代码
test(); // 第2次进入函数内部执行代码
test(); // 第3次进入函数内部执行代码
}
test()
{
// 在进入游戏场景时创建数据段变量dataVar,设定初始值为1000,此语句不会运行第二次
static dataVar = 1000;
// 在控制台打印dataVar的值
server_print("dataVar = %d", dataVar);
// dataVar储存的值增加2
dataVar += 2;
} // 离开dataVar作用域,并不会删除dataVar
打印内容:
dataVar = 1000;
dataVar = 1002;
dataVar = 1004;
栈变量的声明语句允许重复执行,离开变量作用域时会被删除。
因此,无论栈变量被如何修改,重新创建后仍会得到新的初始值。
#include <amxmodx>
public plugin_init()
{
test(); // 第1次进入函数内部执行代码
test(); // 第2次进入函数内部执行代码
test(); // 第3次进入函数内部执行代码
}
test()
{
// 创建栈变量tempVar,设定初始值为1000
new tempVar = 1000;
// 在控制台打印tempVar的值
server_print("tempVar = %d", tempVar);
// tempVar储存的值增加2,这没有意义,因为他将要被删掉了
tempVar += 2;
} // 离开tempVar作用域,删除tempVar
打印内容:
tempVar = 1000;
tempVar = 1000;
tempVar = 1000;