c指针减量安全/不安全?

c指针减量安全/不安全?,c,pointers,unsafe-pointers,C,Pointers,Unsafe Pointers,分析一些代码: static volatile UCHAR *pucSndBufferCur; eMBErrorCode eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) { if( eRcvState == STATE_RX_IDLE ) { /* First byte before the Modbus-PDU is the slave address. *

分析一些代码:

static volatile UCHAR *pucSndBufferCur;

eMBErrorCode eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )
{
    if( eRcvState == STATE_RX_IDLE )
    {
        /* First byte before the Modbus-PDU is the slave address. */
        pucSndBufferCur = ( UCHAR * ) pucFrame - 1;

        /* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */
        pucSndBufferCur[0] = ucSlaveAddress;
这看起来不安全,如果地址中的内存(pucFrame-1)已经用于其他变量,并且重写它可能会导致故障,该怎么办


你认为这样的代码是可以使用的还是错误的,永远不应该使用?

语句的行为
pucSndBufferCur=(UCHAR*)pucFrame-1pucFrame
是指向数组中某个元素的指针,或者正好在数组末尾之后,并且前面有一个元素,否则code>将是未定义的。为此,可以将标量视为长度为1的数组

这是因为指针算法仅在数组中有效


您还丢弃了
const
,这可能会再次使程序处于未定义状态,具体取决于您对指针的操作(C和C++之间的规则不同)。

请清除问题的意义。 无论如何,代码有点不安全,但不是因为你说的原因。 为了使它更健壮,您应该针对null进行测试。 指针算法有点危险,但我认为这段旧代码会根据上下文做出一些假设

它似乎来自:

FreeModbus库:Modbus ASCII/RTU的便携式Modbus实现。 3*版权所有(c)2006克里斯蒂安·沃尔特

所以,是的,2006年的代码可能很危险,但另一方面,它已经被使用了15年。。。所以它可以被使用。(旧代码通常有效,但如果您不修改它…)

来自此注释

    /* First byte before the Modbus-PDU is the slave address. */
    pucSndBufferCur = ( UCHAR * ) pucFrame - 1;
我们可以推断函数期望调用方保证这一点。在这种情况下,如果调用方满足要求,那么代码是安全的

如果调用方不能保证这一点,则函数是不安全的。这就像您无法有效检查的任何其他先决条件一样:如果违反了要求,则它们具有UB,这是调用方的错误

相比之下,
free()
如果违反了从
malloc()/realloc()
返回指针参数的先决条件,则可能会有类似的行为(可能还有更糟糕的副作用)

这看起来不安全,如果地址中的内存(pucFrame-1)已经用于其他变量,并且重写它可能导致故障,该怎么办

它是不安全的-它是C。正确使用它的责任是你的。如果您错误地使用它(传递不符合规定要求的指针),将出现故障,这将是您的错误

你认为这样的代码是可以使用的还是错误的,永远不应该使用

它可以安全使用,就像
free()
可以安全使用一样。它可能被错误地使用,就像
free()
可能被误用一样。不使用这种代码的唯一原因是您不相信自己能正确使用它



实用的建议是查看此
pucFrame
指针的来源,验证它始终保证满足要求,然后确保在指针遍历代码的过程中没有中断任何内容。

除非检查数组边界内的内容,否则不要假设某个内容位于某个特定地址之前或之后

MISRA-C:2004,规则17.4(必需)或MISRA-C:2012,规则18.4(必需)数组索引应是唯一允许的指针算法形式

强烈建议您使用诸如PC Lint之类的静态分析器来检查代码的健全性,以避免未定义的行为


此外,您可以将所有必需的内容放入一个结构中,只需向函数传递一个结构指针。但即使如此,也不要使用++或--访问结构成员,因为您将不知道添加的填充依赖于编译器

尽管未预先检查可能不安全,但它仍然依赖于上下文。这意味着在某些情况下,它不一定是坏的-但是,在编写自己的代码时,最好避免这些假设,例如
pucFrame-1
,最好使用适当的结构转换和其他方法来避免错误。但是,这些结构也被广泛使用,并且不一定是错误的……支持“Modbus PDU之前的第一个字节是从地址”的结构定义是什么?如果C实现定义了它,行为也将被定义。如前所述,关于从属地址的注释表明,在工作中存在实现定义的行为。