---
title: "脚本编写: 标签 | open.mp"
description: "关于标签（Tags）的指南，这是Pawn语言中一种类类型特性，为处理不同用途的值提供安全机制。"
canonical: https://omp.itsneufox.com/zh-CN/docs/scripting/language/Tags
language: zh-CN
---

# 脚本编写: 标签

## 引言

标签（Tag）是变量的前缀，用于告知编译器在特定情况下特殊处理该变量。例如你可以通过标签定义变量的使用范围，或者指定变量的特殊运算方式。

标签分为两种类型：

-   **强标签**（以大写字母开头）
-   **弱标签**（以小写字母开头）

两者的主要区别在于：弱标签在某些情况下可能被编译器静默转换为无标签变量（即不会产生警告），而强标签在隐式转换时总会触发警告。

以下是一个简单示例：

```c
new
    File:myfile = fopen("file.txt", io_read);
myFile += 4;
```

`fopen`函数返回带有`File:`标签的值，首行赋值操作没有问题（注意标签大小写需一致）。但第二行对文件句柄进行数值加法运算时，`4`是无标签值，而`myFile`带有`File:`标签，这种类型不匹配将触发编译器警告。这种机制非常有用，因为文件句柄的实际数值没有意义，修改它会导致句柄失效从而无法关闭文件。

### 强标签

强标签以大写字母开头，SA:MP 中的常见示例包括：

```c
Float:
File:
Text:
```

强标签变量不可与其他类型混用，以下操作都会触发警告：

```c
new
    Float:myFloat,
    File:myFile,
    myBlank;

myFile = fopen("file.txt", io_read); // File: = File:，无警告

myFloat = myFile; // Float: = File:，"标签不匹配"警告

myFloat = 4; // Float: = _:（无标签），"标签不匹配"警告

myBlank = myFloat; // _:（无标签） = Float:，"标签不匹配"警告
```

### 弱标签

弱标签的行为与强标签基本相似，但当目标变量无标签时，弱标签转换不会触发警告：

```c
new
    Strong:myStrong,
    weak:myWeak,
    myNone;

myNone = myStrong; // 触发警告
myNone = myWeak; // 无警告
```

但反向操作仍会触发警告：

```c
myWeak = myNone; // 触发警告
```

函数参数传递同理：向无标签参数传递弱标签变量不会触发警告：

```c
new
    weak:myWeak;
MyFunction(myWeak);

MyFunction(myVar)
{
    ...
}
```

但向带标签参数（无论强弱）传递无标签参数会触发警告。SA:MP 中弱标签的典型示例包括：

```c
bool:
filemode:
floatround_method:
```

## 使用方法

### 声明变量

声明带标签变量非常简单，直接书写标签即可（无需预先定义标签）：

```c
new
    Mytag:myVariable;
```

使用现有标签声明变量后，即可将该变量用于该标签对应的函数和运算符。

### 函数定义

定义带标签参数的函数时，只需在参数或返回值前添加标签：

```c
Float:GetValue(File:fHnd, const name[])
{
    ...
}
```

此函数接收文件句柄并返回浮点数值（假设是从文件中读取并与`name[]`参数传递的数值名称对应的值）。此函数很可能使用`floatstr`函数（通过在 Pawno 右侧函数列表点击此函数时查看状态栏可知，此函数也返回`Float:`类型值）进行字符串转换。虽然具体实现细节无关紧要，但其核心逻辑是将字符串转换为 IEEE 浮点数值，并以 PAWN 单元(cell)形式存储（实际上严格存储为整型数值，只是其位模式恰好与对应的 IEEE 浮点数一致——这正是标签机制部分要解决的问题，因为 PAWN 本身是无类型语言）。

### 运算符重载

运算符（例如 `+`、`==`、`>` 等）可为不同标签实现重载。这意味着对两个`Float:`变量执行`+`运算，其行为将与无标签变量的加法运算截然不同。该特性对浮点型变量尤为重要——如先前所述，`Float:`变量并非真正的浮点数，而是采用特定位模式的整型存储。若未重载运算符，这些运算将在整型层面直接执行，若将结果重新解释为浮点数将产生无效结果。因此`Float:`标签重载了多数运算符，通过调用服务端的特殊数学函数实现运算（而非在 PAWN 脚本层处理）。

运算符重载函数的定义方式与普通函数类似，区别在于需使用"operator(**符号**)"语法代替函数名，其中(**符号**)代表被重载的运算符。可重载的合法运算符包括：

```c
+
-
=
++
--
==
*
/
!=
>
<
>=
<=
!
%
```

诸如`\`、`*`、`=`等运算符会被自动处理。而`&`等位运算符无法被重载。你还可以针对不同的标签组合多次重载同一个运算符。例如：

```c
stock Float:operator=(Mytag:oper)
{
    return float(_:oper);
}
```

添加此代码后，以下操作将不再触发警告：

```c
new
    Float:myFloat,
    Mytag:myTag;

myFloat = myTag;
```

由于`Float: = Mytag:`这种情况下的赋值运算符`=`已被显式处理，编译器现在能够准确理解其操作逻辑，因此你将不再收到此前会出现的编译器警告。

### 标签覆盖

使用`_:`前缀可强制忽略变量标签。但需谨慎处理类型转换：

```c
return float(_:oper);
```

这是标签覆盖的典型示例。操作数前的`_:`表示编译器将忽略`oper`变量原有的`Mytag:`标签类型，强制将其视为`_:`标签类型（即无标签类型）。`float()`函数用于将普通数值标记为浮点类型，因此必须接收无标签数值。在此示例中，我们假设`Mytag`存储的是普通整型数值，但进行标签覆盖时必须格外谨慎。例如下列操作将产生异常结果：

```c
new
    Float:f1,
    Float:f2 = 4.0;
f1 = float(_:f2);
```

根据常识推断，`f1`应被赋值为`4.0`，但实际结果并非如此。如前所述，`f2`变量存储的是`4.0`的 IEEE 浮点位模式表示（而非简单的整型数值`4`），这意味着当你要求编译器将该变量作为整型处理时，它会直接将变量中的位模式作为整型值读取（而不会执行浮点到整型的数值转换）。因此你将得到一个看似随机的数字（实际上该数值遵循 IEEE 浮点规范的结构规律，但其整型表现形式与`4.0`毫无相似性）。
