字面量(Literal)用于表示一个或多个具体的数值。可用于做运算,或为标识符赋值。
AMXXPawn只有整数,不存在浮点数。而整数的类型是int32(在AMXXPawn中称为cell)。
字面量能表达的单个数值范围是-2147483648~2147483647。
字面量可简单分为单值字面量、数组字面量。
单值字面量可细分为以下几个类型:
数组字面量可细分为以下几个类型:
单值字面量是不可再分解的最小计算单元,属于原子表达式,例如:0b_1111、1024、0xFF、512.0
数组字面量或与运算符组合的单值字面量,属于复合表达式,例如:{ 1, 2, 3 }、-512、 256 + 256
任何字面量都在编译时就能确定数值,因此全都属于常量表达式。
然而数组字面量本质是创建一个数据段匿名变量,因此仅在对命名变量初始化时会被编译器认定为常量表达式。
字符字面量通常指的是ASCII码表中的128个字符(不含中文,详情百度ASCII码表)。
字符字面量的正确写法是:以单引号'作为开头和结尾,中间填写1个ASCII字符。
例如:'a' 'b' 'c' '1' '2' '3'
每个字符字面量都对应一个具体的数值,与ASCII码表中字符编码一致。
例如:
转义指示符可以表示一些不可见或键盘按不出来的字符,这种表示方式称为转义字符。
| 转义字符 | 解释 |
|---|---|
| '^a' | 蜂鸣符 等于十进制7 |
| '^b' | [BACKSPACE]退格键 等于十进制8 |
| '^e' | [ESC]退出键 等于十进制27 |
| '^f' | 换页符 等于十进制12 |
| '^n' | 换行符 等于十进制10 |
| '^r' | 回车符 等于十进制13 |
| '^t' | [TAB]水平制表符 等于十进制9 |
| '^v' | 垂直制表符 等于十进制11 |
| '^^' | [^]键自己 等于十进制94 |
| '^'' | [']单引号 等于十进制39 |
| '^"' | ["]双引号 等于十进制34 |
| '^%' | [%]百分号 等于十进制37 |
| '^ddd;' | ddd可以填十进制数值 分号;可省略 '^114514'直接等于114514 '^114514' % 256 = 82 = 'Q' |
| '^xhhh;' | hhh可以填十六进制数值,不区分大小写 分号;可省略 '^x1BF52'直接等于114514 '^x1BF52' % 256 = 82 = 'Q' |
编译器指令#pragma ctrlchar '^'可以更改转义指示符,若不更改,默认为^字符。
若更改转义指示符,则'^^'也要相应改变,例如将转义指示符改为\,要表示字符\就得写成'\\'
注意:终止符'^0'或'^x0'等于十进制0,而零字符'0'等于十进制48,不要混淆。
十进制指的是逢十进一,二进制类似,是逢二进一。
二进制整数字面量的正确写法:以0b作为开头,后续跟随任意数量的_、0、1,下划线没有实际意义。
整数最大值+1会变为最小值。这与二进制对最小值和最大值的定义以及逢二进一的机制有关。
0b_01111111_11111111_11111111_11111111 + 1
= 0b_10000000_00000000_00000000_00000000
= -2147483648
十进制整数字面量正确写法:以任意数字开头,后续跟随任意数量的_或数字。
若写出来的数值超出cell(int32)能表示的数值范围,得到的数值等于:除以最大值然后求模的结果。
例如6442450944实际等于6442450944 % 2147483648等于0。
AMXXPawn默认情况下不允许编写浮点数字面量,会在编译时触发报错。
必须使用#pragma rational指令设置一个浮点数标签,才允许使用浮点数字面量。
由于float.inc文件中包含这个指令,而amxmodx.inc文件引用了float.inc文件,只需引用amxmodx.inc文件便能达到一样效果。
浮点数字面量在被编译器解析时,解析器会访问浮点数的二进制表示,将其解释为一个32位整数。
因此,虽然看着是浮点数,但数值在AMXXPawn仍是整数,核心模块提供的接口函数在得到这个整数时会自动转换回浮点数。
因为会转换回浮点数,我们通常不需要担心计算结果错误,但这导致AMXXPawn对于浮点数的运算效率要低一些。
浮点数字面量自带Float标签(#pragma rational Float指令设定的),与其它表达式做运算会被警告标签不匹配。
浮点数能表示的最小值是无穷小,但只能用整数字面量表示:Float:0b_11111111_10000000_00000000_00000000
浮点数能表示的最大值是无穷大,但只能用整数字面量表示:Float:0b_01111111_10000000_00000000_00000000
浮点数字面量最小有限值:-340282346638528800000000000000000000000.0(或-3402823466385288.0e23)
浮点数字面量最大有限值:340282346638528800000000000000000000000.0(或3402823466385288.0e23)
十进制指的是逢十进一,十六制类似,是逢十六进一。
十六进制字面量用ABCDEF字母(不区分大小)分别表示10、11、12、13、14、15、16,所以是逢F进一。
十六进制整数字面量的正确写法:以0x作为开头,后续跟随任意数量的_、数字、A~F,下划线没有实际意义。
注意:只有末端的8个数字和字母是有效的
若写出来的数值超出cell(int32)能表示的数值范围,得到的数值等于:除以最大值然后求模的结果。
例如0x_F0000000实际等于4294967296 % 2147483648等于0。
任何数组字面量都储存在数据段,并且相同内容的字面量储存在不同的数据段地址,每一个都是可修改的。
多个单值常量表达式用逗号隔开,再用{ }包裹它们,就能形成一维数组字面量。
#include <float>
const CONSTANT = 512 + 512;
// 数组字面量的花括号{ }可以含有任意常量表达式
static array1[] = { '8', 0b_11111111, 255, 0xFF, 127 + 128, CONSTANT };
static Float:array2[] = { 32.0, 64.0, 128.0, 256.0 };
数组字面量和数组略有不同。数组指的是数组类型的变量,变量拥有名称,而数组字面量是储存在数据段的匿名变量。
因为数组字面量是变量,所以被按引用传递到函数内时,可以被函数更改内容。而真正的常量表达式是不会被更改的。
一维数组字面量之上还有二、三维数组字面量,AMX Mod X 1.8.2以上版本扩展到四维。
正确的编写方法应该参照变量声明语句所设定的规则:变量维度、变量初始化
任何字符串字面量都储存在数据段,并且相同内容的字面量储存在不同的数据段地址,每一个都是可修改的。
转义字符串字面量(普通字符串字面量)是最常用的字符串字面量,特点是像字符字面量一样,内部允许填写转义字符。
转义字符串字面量的正确写法:以"作为开头和结尾,中间填写任意数量的字符(包括转义字符),例如:"中文^t"
有时候我们会关注字面量的长度和尺寸。
长度指的是第一个终止符之前有多少个cell储存数据。
尺寸总共有多少个cell储存数据。
若源码是UTF8编码,每个ASCII字符占用1个cell,每个转义字符占用1个cell,每个中文占用3个cell。
字面量末端会自动增加1个终止符,占用1个cell。
一个cell拥有4字节的储存空间,但UTF8编码下,1个ASCII字符只需要1字节空间,1个中文只需要3个字节空间。
也就是说,非压缩字符串字面量用1个cell去储存1个数据,浪费了3/4的空间。
使用压缩字符串字面量就能紧凑储存这些数据,大幅度改善这一情况。
若一个字符串字面量的左边紧贴着!感叹号,则内容会在编译时被压缩,例如:!"中文^t"、!^"中文^t"
压缩后,每个ASCII字符占1个字节,每个中文占3个字节,每4个字节占1个cell,剩下的不足4字节也占1个cell。
素字符串字面量(未加工字符串字面量)与转义字符串字面量相反,是不支持转义字符的。
若一个字符串字面量的左边紧贴着^转义指示符,则是素字符串字面量,例如:^"中文^t"、^!"中文^t"
所有转义字符会原模原样的存入,不转变为其它字符。例如^48本该转变为0字符,但素字符串会直接储存^、4、8三个字符。
转义字符串字面量的左边加上!和转义指示符,则是压缩素字符串字面量,例如:^!"中文"、!^"中文"
结构体字面量是允许含有任意常量表达式的一维数组字面量,例如: { "急速僵尸", { 0.0, 0.0, 17.0 }, 1000, 1.0 }
仅在为结构体(数组+枚举组合而成)赋值时,才允许根据其结构编写对应的字面量。
这种字面量虽然有时候看起像是多维的,但必须使用相同结构的一维数组变量才能储存,否则会被编译器视作语法错误。