0

说我有两个“模块”。例如,RS-232 端口的硬件接口层及其上方的一层使其更加抽象。

我有一个这样的接收缓冲区:U8BIT myBuffer[MAX]. U8BIT是类型化的:typedef unsigned char

然而,可以接收两种类型的消息。一个有标题,另一个没有标题。这个逻辑已经写好了。

“上面的层”将访问此缓冲区,但它不应该知道这是一个标头还是无标头消息。

因此我有这样的功能:

U8BIT * fooBuffer(U8BIT * maxLength)
{
    U8BIT * retval;
    if( isHeaderless() )
    {
        retval = &(myBuffer[0]);
        *maxLength = MAX;
    }
    else
    {
        retval = &(myBuffer[5]);
        *maxLength = MAX - 5;
    }
    return retval;
}

如何确保调用此函数的任何函数都无法更改返回指针的内容?

是的,我知道这将永远是可能的。不要试图让其他人更难尝试修改它。我希望它是“不可能的”,这样就不会更容易出错,因为如果你尝试修改const.

我可以将函数声明如下:const U8BIT * fooBuffer(U8BIT * maxLength)

4

4 回答 4

1

如何确保调用此函数的任何函数都无法更改返回指针的内容?

返回一个指向它的指针const,它将向您的代码用户表明您的意图。
但是,请注意,不能保证他们无法修改它。请记住,他们可以,如果他们这样做,那将是一个未定义的行为

您只能遵循正确的语义,并希望有人不会滥用指针黑客来破坏您的代码。只要可以访问代码,总是有可能破坏代码。因此,您所能做的就是清楚地表达您的意图。

于 2012-06-28T13:15:27.107 回答
1

用作const U8BIT *函数的返回类型。

例如在你的函数中:

const U8BIT * fooBuffer(U8BIT * maxLength)
{
    U8BIT * retval;  

    // code

    return (const U8BIT *) retval;
} 

如果retval指针没有在你的fooBuffer函数中被取消引用,也将它声明为const U8BIT *,然后不再需要在 return 语句中进行强制转换。

于 2012-06-28T13:15:44.657 回答
1

我自己的经验法则是:每当我有从函数返回指针的冲动时,我认为这是一个大红旗,说明我的程序设计很糟糕。尽管返回 const 指针可能是该规则的一个罕见例外。

在您的情况下,代码可能会从重新设计中受益。这是我的建议。

#define FIRST_INDEX       0u
#define SOME_OTHER_INDEX  5u
#define N                 SOMETHING

static const uint8_t MAX = something;
static uint8_t myBuffer [N];


uint8_t fooBuffer (const uint8_t* retVal)
{
    uint8_t maxLength;

    if( isHeaderless() )
    {
        retval = &myBuffer[FIRST_INDEX];
        maxLength = MAX;
    }
    else
    {
        retval = &myBuffer[SOME_OTHER_INDEX];
        maxLength = (uint8_t) (MAX - SOME_OTHER_INDEX);
    }

    return maxLength;
}

程序设计变更:

  • 确保 myBuffer 是一个私有变量,不能在您的代码模块之外访问或更改。
  • 按值而不是指针返回 maxLength。我不明白你为什么需要通过指针返回它。
  • retVal 通过一个 const 指针返回。

编码风格变化:

  • 删除了 U8BIT 类型并用 C99/C11 兼容的 uint8_t 替换它。如果您没有 C99/C11 编译器,只需在typedef unsigned char uint8_t某个地方。这使您的代码更容易被其他程序员阅读。如果您使用自己的特殊类型,他们可能会错误地开始怀疑该特定类型有什么神奇之处。
  • 删除了 &myBuffer[] 周围的模糊括号,因为它没有任何意义。
  • 删除了幻数。

MISRA-C:2004 合规性:(因为您标记了此 MISRA)

  • u每个整数常量文字都需要后缀。
  • 您必须将-运算符的结果类型转换为基础类型 uint8_t。
于 2012-07-04T09:52:09.560 回答
0

是的,已经开始使用const合格的返回值了。

但是你可以走得更远,将一个值返回到一个真正不可修改的地方。如果我没看错,你只有两个可能的返回值:

... myBuffer... // supposing that this is known at compile time

static U8BIT const retval0 = &(myBuffer[0]);
static U8BIT const retval1 = &(myBuffer[5]);

U8BIT const* fooBuffer(U8BIT * maxLength)
{
    if(isHeaderless()) return &retval0;
    else return &retval1;
}

您的平台甚至可能有办法确保两者retval最终位于只读部分。

于 2012-06-28T13:46:27.187 回答