指针引用的 CoDeSys 大小
CoDeSys size of pointer reference
使用 Codesys v2.3,我正在尝试制作一个功能块来检查指针数据的大小,以免写入超出此范围的内存部分。
例如:
VAR_INPUT
pData: POINTER TO REAL; // Or pointer to WORD or ARRAY[1..x] ...
END_VAR
VAR_OUTPUT
DataSize: DWORD;
END_VAR
IF SIZEOF(pData^) <> 4 THEN
RETURN;
END_IF
DataSize := SIZEOF(pData^);
现在,如果我将 BYTE 的地址放入此块的 pData 中,IF 仍会检查,因为解除引用的指针似乎 return 我们指向的大小(在这种情况下是真实的)。
我知道可以要求将大小作为输入,但如果遗漏或输入错误,这可能是一个潜在的问题,因为它会以其他方式扰乱程序
有没有办法检查指向的任何数据的大小,同时避免外部输入?
据我所知,无法检测指针的数据类型是什么,因为它只是一个内存地址。如您所说,您应该提供指针目标的大小作为其他参数。只需添加一个检查指针不为零且大小不为零以防止(某些)问题。
其他环境的解决方案:
对于 TwinCAT 3,可以通过使用 T_Arg
和 F_INT
等助手来创建单输入解决方案,但我认为 Codesys 2 没有它们(有人确认过吗?)。在该解决方案中,您无论如何都必须更改函数调用,这样指针就不会成为输入。
在该解决方案中,您可以创建一个输入为 T_Arg
的函数。然后通过为每种数据类型使用辅助函数来调用它。从T_Arg
可以获取数据类型、大小和数据位置。
FUNCTION_BLOCK FB_Test
VAR_INPUT
Test : T_arg;
END_VAR
Test.eType; //Data type
Test.cbLen; //Variable data length in bytes
Test.pData; //Pointer to data
并调用它:
test is an instance of FB_Test
//INT for example
//Now the cblen = 2
test(
Test := F_INT(PointerToInt^)
);
//REAL for example
//Now the cbLen = 4
test(
Test := F_REAL(PointerToReal^)
);
这可能有点跑题了,对此深表歉意,希望对大家有所帮助。仍然希望有人知道更好的解决方案。
编辑
实际上找到了其他很好的解决方案,但我认为它也只适用于 TwinCAT 3。只是想 post 也在这里。
通过使用 ANY
数据类型,可以将任何东西作为参数并获取它的大小。区别在于它不会接受 POINTER
作为输入。
FUNCTION_BLOCK FB_Test2
VAR_INPUT
Test : ANY;
END_VAR
VAR_OUTPUT
Size : DINT;
END_VAR
//diSize contains size of the input data type
size := Test.diSize;
用法:
//test2 is an instance of FB_Test2
//Output "Size" is 4, as this is a REAL
test2(
Test := PointerToReal^
);
为什么你需要这样一个函数,只是为了检测变量大小,而这个函数已经存在了?
您所要做的就是直接在您的程序中调用 SIZEOF()
。您不需要使用指针。据我了解,您使用它们是因为您想让输入变量成为任何类型的通用变量,而不是因为您在程序中使用了指针。所以原来的变量都是直接分配的
您的函数试图在不更改计算算法的情况下围绕 SIZEOF()
创建环绕,然后只需使用 SIZEOF()
,因为这就是此函数的用途。
告诉我你为什么要尝试创建单独的函数,而我
我会相应地更改答案。
我假设您需要检查变量的大小是否是您需要的。然后就可以做一个函数了。
FUNCTION IsSize : BOOL
VAR_INPUT
VarSize: INT;
CompareTo: INT;
END_VAR
IsSize := (VarSize = CompareTo);
END_FUNCTION
然后你可以这样称呼它
VAR
MyVar: REAL;
END_VAR
IF IsSize(SIZEOF(MyVAR), 4) THEN
// DO something
END_IF
编辑:使用数组
如果您想创建一个与数组一起使用的函数,并且您希望能够传递无限数量的元素数组,那么您可以这样做。
FUNCTION ArrSize : BOOL
VAR_INPUT
MyArr: POINTER TO ARRAY[0..1000] OF BOOL;
ArrNum: INT; (* Number of array elements *)
ArrStart: INT; (* First index of an array *)
END_VAR
VAR
iCount : INT := 0;
END_VAR
FOR iCount := ArrStart TO ArrNum DO
MyArr^[iCount] := TRUE;
END_FOR
END_FUNCTION
然后在代码中你可以
VAR
aTest: ARRAY[0..20] OF BOOL;
END_VAR
ArrSize(ADR(aTest), SIZEOF(aTest), 0);
使用 Codesys v2.3,我正在尝试制作一个功能块来检查指针数据的大小,以免写入超出此范围的内存部分。
例如:
VAR_INPUT
pData: POINTER TO REAL; // Or pointer to WORD or ARRAY[1..x] ...
END_VAR
VAR_OUTPUT
DataSize: DWORD;
END_VAR
IF SIZEOF(pData^) <> 4 THEN
RETURN;
END_IF
DataSize := SIZEOF(pData^);
现在,如果我将 BYTE 的地址放入此块的 pData 中,IF 仍会检查,因为解除引用的指针似乎 return 我们指向的大小(在这种情况下是真实的)。
我知道可以要求将大小作为输入,但如果遗漏或输入错误,这可能是一个潜在的问题,因为它会以其他方式扰乱程序
有没有办法检查指向的任何数据的大小,同时避免外部输入?
据我所知,无法检测指针的数据类型是什么,因为它只是一个内存地址。如您所说,您应该提供指针目标的大小作为其他参数。只需添加一个检查指针不为零且大小不为零以防止(某些)问题。
其他环境的解决方案:
对于 TwinCAT 3,可以通过使用 T_Arg
和 F_INT
等助手来创建单输入解决方案,但我认为 Codesys 2 没有它们(有人确认过吗?)。在该解决方案中,您无论如何都必须更改函数调用,这样指针就不会成为输入。
在该解决方案中,您可以创建一个输入为 T_Arg
的函数。然后通过为每种数据类型使用辅助函数来调用它。从T_Arg
可以获取数据类型、大小和数据位置。
FUNCTION_BLOCK FB_Test
VAR_INPUT
Test : T_arg;
END_VAR
Test.eType; //Data type
Test.cbLen; //Variable data length in bytes
Test.pData; //Pointer to data
并调用它:
test is an instance of FB_Test
//INT for example
//Now the cblen = 2
test(
Test := F_INT(PointerToInt^)
);
//REAL for example
//Now the cbLen = 4
test(
Test := F_REAL(PointerToReal^)
);
这可能有点跑题了,对此深表歉意,希望对大家有所帮助。仍然希望有人知道更好的解决方案。
编辑 实际上找到了其他很好的解决方案,但我认为它也只适用于 TwinCAT 3。只是想 post 也在这里。
通过使用 ANY
数据类型,可以将任何东西作为参数并获取它的大小。区别在于它不会接受 POINTER
作为输入。
FUNCTION_BLOCK FB_Test2
VAR_INPUT
Test : ANY;
END_VAR
VAR_OUTPUT
Size : DINT;
END_VAR
//diSize contains size of the input data type
size := Test.diSize;
用法:
//test2 is an instance of FB_Test2
//Output "Size" is 4, as this is a REAL
test2(
Test := PointerToReal^
);
为什么你需要这样一个函数,只是为了检测变量大小,而这个函数已经存在了?
您所要做的就是直接在您的程序中调用 SIZEOF()
。您不需要使用指针。据我了解,您使用它们是因为您想让输入变量成为任何类型的通用变量,而不是因为您在程序中使用了指针。所以原来的变量都是直接分配的
您的函数试图在不更改计算算法的情况下围绕 SIZEOF()
创建环绕,然后只需使用 SIZEOF()
,因为这就是此函数的用途。
告诉我你为什么要尝试创建单独的函数,而我 我会相应地更改答案。
我假设您需要检查变量的大小是否是您需要的。然后就可以做一个函数了。
FUNCTION IsSize : BOOL
VAR_INPUT
VarSize: INT;
CompareTo: INT;
END_VAR
IsSize := (VarSize = CompareTo);
END_FUNCTION
然后你可以这样称呼它
VAR
MyVar: REAL;
END_VAR
IF IsSize(SIZEOF(MyVAR), 4) THEN
// DO something
END_IF
编辑:使用数组
如果您想创建一个与数组一起使用的函数,并且您希望能够传递无限数量的元素数组,那么您可以这样做。
FUNCTION ArrSize : BOOL
VAR_INPUT
MyArr: POINTER TO ARRAY[0..1000] OF BOOL;
ArrNum: INT; (* Number of array elements *)
ArrStart: INT; (* First index of an array *)
END_VAR
VAR
iCount : INT := 0;
END_VAR
FOR iCount := ArrStart TO ArrNum DO
MyArr^[iCount] := TRUE;
END_FOR
END_FUNCTION
然后在代码中你可以
VAR
aTest: ARRAY[0..20] OF BOOL;
END_VAR
ArrSize(ADR(aTest), SIZEOF(aTest), 0);