说我有两个'模块'。例如,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)
答案 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;
}
计划设计变更:
编码样式更改:
typedef unsigned char uint8_t
。这使得其他程序员更容易阅读您的代码。如果您使用自己的特殊类型,他们可能会错误地开始怀疑该特定类型有什么神奇之处。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
最终位于只读部分。