AMXXPawn编译器指令#define

#define宏定义指令使用方法:

#define 宏名 #define 宏名 替换宏名的代码

功能1:定义宏名(宏定义符号),从下一行开始让defined(宏名)返回true(AMXX1.8.3以下版本返回1).这种用法常见于inc文件的顶部.

示例:

#include amxmodx public plugin_init() { register_plugin("测试插件", "1.0.0", "插件作者"); server_print("[AMXX]defined(name) = %d", defined(name)); #define name server_print("[AMXX]defined(name) = %d", defined(name)); }

进入游戏后,按下 [~] 按键打开控制台,可以看见打印结果:

[AMXX]defined(name) = 0 [AMXX]defined(name) = 1

需要注意,任何"指令"和"运算词"都是在编译时执行的,而函数体内的其它代码是在游戏运行时执行的.

不要以为#definedefined在函数体内就会像newstatic一样在游戏运行时执行.

编译时,代码中的所有defined已经被替换为truefalse(0或1).而不是在函数运行过程中临时发生变化.

功能2:定义宏名替换宏名的代码,从指令语句下一行开始,将源码中所有宏名替换掉.

示例:

#include amxmodx #define dPluginName "测试插件" #define dPluginVersion "1.0.0" #define dPluginAuthor "插件作者" public plugin_init() { register_plugin(dPluginName, dPluginVersion, dPluginAuthor); server_print("[AMXX]插件名称 = %s", dPluginName); server_print("[AMXX]插件版本 = %s", dPluginVersion); server_print("[AMXX]插件作者 = %s", dPluginAuthor); }

进入游戏后,按下 [~] 按键打开控制台,可以看见打印结果:

[AMXX]插件名称 = 测试插件 [AMXX]插件版本 = 1.0.0 [AMXX]插件作者 = 插件作者

#define宏定义指令的高级用法:

高级用法必须了解宏定义指令的书写规则.

首先需要了解标识符命名规则:

在AMXX1.8.3以下版本中,符号名称不得超过31个字节.

在AMXX1.8.2以上版本中,符号名称不得超过63个字节.

符号名区分大小写,比如fooFoo是两个不同的符号.

名称的第一个字符必须是"_ @ az AZ"这四者之一.

名称的剩余字符必须是"_ @ az AZ 09"这五者之一.

宏名不完全受到这些规则限制,但编译器实际只认可符合该规则的部分.

编译器会认为"_@AA我爱你"和"_@AA他爱我"这样的两个宏名是相同的.因为名称左边的"_@AA"符合正常书写规则,而且相同.

接下来了解宏名的书写规则:

宏名的首字符必须是"_ @ az AZ"这四者之一.

宏名总字节数不得超过标识符命名规则所限.

宏名可以含有转义字符.不能含有回车符或换行符.

宏名含有不符合标识符命名规则的字符.后续内容可用 %0%10 表示外界输入的参数(代码).若有重复参数,则该参数对应最后输入的代码.

若参数被 ( ) 圆括号包裹,参数的后续内容可以是连续的空格或制表符之一.

若名称内含有 ( 左圆括号,右边必须至少有1个 ) 右圆括号.且名称终止位置是最后1个 ) 右圆括号右边的第1个空白字符.

若名称内不含 ( 左圆括号,名称终止位置是右边的第1个空白字符.

然后是了解替换宏名的代码的书写规则:

必须用空白字符将宏名替换宏名的代码隔开.

内容可以是残缺或完整的语句或表达式,不能是注释.多个语句必须用 , 逗号或 ; 分号相隔.

可以用 %0%10 引用外界输入的代码.编号必须与宏名使用的一致,顺序无限制,使用次数无限制.

若以 \ 反斜杠结尾,下一行也是用于替换宏名的代码.但替换时不会保留换行符.本质上仍然是一行代码.

若后续内容全是空白字符或注释.表示替换宏名的代码已经书写完毕.这些空白字符和注释不会被用于替换宏名.

示例:

#include amxmodx // ^48和^50是转义字符,对应0和2 #define dCustom((叭叭叭^48Add(^50%3a(%4bcc%1)ttt %3 + %4 + %1 public plugin_init() { register_plugin("测试插件", "1.0.0", "插件作者"); server_print("[AMXX]自定义加法(5+6+7) = %d", dCustom((叭叭叭0Add(25a(6bcc7)ttt); }

进入游戏后,按下 [~] 按键打开控制台,可以看见打印结果:

[AMXX]自定义加法(5+6+7) = 18

这种功能可以用来增加阅读理解成本,使一般人看不懂这段代码.开发者可以用这种方法隐藏类似删库跑路的恶劣代码.

实际上,正常情况下不应该如此极端的使用这种书写规则.

以下是正常的使用方法:

// 格式:符号名称(参数列表) 替换文本 // 将名字太长的函数改更短 #define IsAlive(%0) is_user_alive(%0) // 以某种格式自动填写某个参数 #define GetWeaponName(%0,%1) get_weaponname(%0, %1, charsmax(%1)) // 将复杂计算改用简短的代码表示 #define GetVectorLength(%0) floatsqroot(%0[0] * %0[0] + %0[1] * %0[1] + %0[2] * %0[2])

在设定了替换宏名代码情况下,拥有 ( ) 圆括号的宏名通常被称呼为宏函数,或函数宏.

而没有 ( ) 圆括号,且替换宏名代码是常量表达式的,通常被称呼为宏常量,或常量宏.