Skip to main content

影子规则

CODESYS,通常允许您对不同的元素使用相同的标识符。例如,一个 POU 和一个变量可以命名相同。但是,您应该避免这种做法,以防止混淆。

306. 例子

反例:在以下代码片段中,本地功能块实例与函数同名:

在这种情况下,不清楚程序中调用的是实例还是函数。

FUNCTION YYY : INT
;
END_FUNCTION

FUNCTION_BLOCK XXX
;
END_FUNCTION_BLOCK

PROGRAM PLC_PRG
VAR
    YYY : XXX;
END_VAR
YYY();
END_PROGRAM


隐藏时的编译器行为

如果相同的标识符用于不同的元素,编译器不会报告任何错误或警告。相反,编译器以特定顺序搜索代码以查找标识符的声明。如果找到声明,则编译器不会在别处搜索任何其他声明。如果确实存在其他声明,那么它们将被编译器“隐藏”。以下部分描述了阴影规则(即编译器在搜索标识符声明时使用的搜索顺序)。 “歧义访问和限定访问”部分提供了防止歧义访问和绕过隐藏规则的方法。

如何防止阴影

为确保名称始终唯一,您应该遵循命名约定,例如变量的某些前缀。

有关更多信息,请参阅: 标识符名称

可以使用静态代码分析自动检查命名约定 CODESYS.静态代码分析还可以检测名称的重复使用 YYY 并将其报告为错误。

同样通过属性的一致使用 qualified_only 对于枚举和全局变量列表,通过使用合格的库,可以避免非唯一情况。

为了确保 POU 中的同名 POU 设备 当 POU 在 POU 视图被调用,操作符 __POOL 当调用 POU 的名称时,应该在前面加上。

例子: svar_pou := __POOL.POU();

应用程序中的搜索顺序

当编译器在应用程序的代码中遇到单个标识符时,它会按以下顺序搜索相应的声明:

  1. 局部变量

    1. 方法的局部变量

    2. 功能块、程序或功能以及任何基本功能块中的局部变量

    3. POU 的局部方法

  2. 应用程序中的全局变量,如果 qualified_only 声明全局变量的变量列表中未设置属性

    1. 应用程序中的全局变量,如果 qualified_only 声明全局变量的变量列表中未设置属性

    2. 父应用程序中的全局变量,如果 qualified_only 声明全局变量的变量列表中未设置属性

    3. 当库和变量列表都不需要限定访问时,引用库中的全局变量

  3. POU 或类型名称

    1. 来自应用程序的 POU 或类型名称(即全局变量列表、功能块等的名称)

    2. 来自父应用程序的 POU 或类型名称

    3. POU 或库中的类型名称

  4. 图书馆

    1. 本地引用的库和由库发布的库的命名空间

  5. 计划书 看法

    1. 中的全局变量 计划书 看来,除非 qualified_only 属性在声明它们的变量列表中设置

    2. POU 或类型名称 计划书 视图(即全局变量列表、功能块等的名称)

    3. 来自的图书馆 计划书

提示

插入到库管理器中的库 POU 视图在项目中所有应用程序的库管理器中以适当的占位符分辨率进行镜像。然后这些库与应用程序中的库形成一个公共命名空间。因此,应用程序中的库不会影响池中的库。

图书馆的检索顺序

当编译器在库的代码中遇到单个标识符时,它会按以下顺序搜索相应的声明:

  1. 局部变量

    1. 方法的局部变量

    2. 功能块、程序或功能以及任何基本功能块中的局部变量

    3. POU 的局部方法

  2. 全局变量

    1. 本地库中的全局变量,如果 qualified_only 声明全局变量的变量列表中未设置属性

    2. 当库和变量列表都不需要合格访问时,引用库中的全局变量

  3. 图书馆

    1. 来自本地库的 POU 或类型名称(即全局变量列表、功能块等的名称)

    2. 来自引用库的 POU 或类型名称

    3. 本地引用库和由本地引用库发布的库的命名空间

模糊访问和合格访问

尽管有这些搜索顺序,仍然会出现不明确的访问。例如,当同名变量存在于不需要限定访问的两个全局变量列表中时就是这种情况。这种情况被编译器报告为错误(例如: 暧昧地使用XXX的名字).

这种模棱两可的用法可以通过限定访问来实现唯一性,例如通过全局变量列表的名称进行访问(例如: GVL.XXX)。

合格的访问也总是可以用来避免遮蔽规则。

  • 全局变量列表的名称可用于唯一访问列表中的变量。

  • 库的名称可用于唯一访问库中的元素。

  • THIS 指针用于唯一访问功能块中的变量,即使功能块的方法中存在同名的局部变量。

要随时查找标识符的声明位置,请使用 编辑→浏览→转到定义 命令。如果编译器产生明显晦涩的错误消息,这将特别有用。

在实例路径中搜索

上述搜索顺序不适用于在实例路径中作为组件存在的标识符或在调用中用作输入的标识符。

对于以下类型的访问 yy.component,它取决于描述的实体 yy 在哪里声明 component 被搜索。

如果 yy 表示具有结构化数据类型的变量(即,类型 STRUCT 或者 UNION), 然后 component 按以下顺序搜索:

  • 功能块的局部变量

  • 基本功能块的局部变量

  • 功能块的方法

  • 基本功能块的方法

如果 yy 表示全局变量列表或程序,则 component 仅在此列表中搜索。

如果 yy 表示库的命名空间,则 component 完全按照上面“在库中的搜索顺序”部分中的描述在此库中搜索。

只有在第二种情况下,编译器才决定是否允许访问找到的元素(即,变量是否只能在本地访问,或者方法是否是私有的)。如果不允许访问,则会发出错误。