我可以要求返回值作为指向常量的指针

时间:2012-06-28 13:13:04

标签: c ansi misra

说我有两个'模块'。例如,RS-232端口的硬件接口层和它上面的层使其更抽象。

我有一个这样的接收缓冲区:U8BIT myBuffer[MAX]U8BIT是typedeffed: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 个答案:

答案 0 :(得分:1)

  

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

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

您只能遵循正确的语义,并希望有人不会滥用指针hackery来破坏您的代码。只要有人可以访问代码,就可以打破代码。所以你能做的就是明确表达你的意图。

答案 1 :(得分:1)

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

例如在你的函数中:

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

    // code

    return (const U8BIT *) retval;
} 

如果在retval函数中没有取消引用fooBuffer指针,则将其声明为const U8BIT *,然后不再需要返回语句中的强制转换。

答案 2 :(得分: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。

答案 3 :(得分: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最终位于只读部分。