问题
I'm having some trouble with a pointer declaration that one of my co-workers wants to use because of Misra C requirements. Misra (Safety Critical guideline) won't let us mere Programmers use pointers, but will let us operate on arrays bytes. He intends to procur a pointer to an array of bytes (so we don't pass the actual array on the stack.)
// This is how I would normally do it
//
void Foo(uint8_t* pu8Buffer, uint16_t u16Len)
{
}
// This is how he has done it
//
void Foo(uint8_t (*pu8Buffer)[], uint16_t u16Len)
{
}
The calling function looks something like;
void Bar(void)
{
uint8_t u8Payload[1024]
uint16_t u16PayloadLen;
// ...some code to fill said array...
Foo(u8Payload, u16PayloadLen);
}
But, when pu8Buffer is accessed in Foo(), the array is wrong. Obviously not passing what it is expecting. The array is correct in the calling function, but not inside Foo()
I think he has created an array of pointers to bytes, not a pointer to an array of bytes.
Anyone care to clarify? Foo(&u8Payload, u16PayloadLen); doesn't work either.
回答1:
In void Foo(uint8_t (*pu8Buffer)[], uint16_t u16Len)
, pu8Buffer
is a pointer to an (incomplete) array of uint8_t
. pu8Buffer
has an incomplete type; it is a pointer to an array whose size is unknown. It may not be used in expressions where the size is required (such as pointer arithmetic; pu8Buffer+1
is not allowed).
Then *pu8Buffer
is an array whose size is unknown. Since it is an array, it is automatically converted in most situations to a pointer to its first element. Thus, *pu8Buffer
becomes a pointer to the first uint8_t
of the array. The type of the converted *pu8Buffer
is complete; it is a pointer to uint8_t
, so it may be used in address arithmetic; *(*pu8Buffer + 1)
, (*pu8Buffer)[1]
, and 1[*pu8Buffer]
are all valid expressions for the uint8_t
one beyond *pu8Buffer
.
回答2:
I take it you are referring to MISRA-C:2004 rule 17.4 (or 2012 rule 18.4). Even someone like me who is a fan of MISRA finds this rule to be complete nonsense. The rationale for the rule is this (MISRA-C:2012 18.4):
"Array indexing using the array subscript syntax, ptr[expr], is the preferred form of pointer arithmetic because it is often clearer and hence less error prone than pointer manipulation. Any explicitly calculated pointer value has the potential to access unintended or invalid memory addresses. Such behavior is also possible with array indexing, but the subscript syntax may ease the task of manual review.
Pointer arithmetic in C can be confusing to the novice The expression
ptr+1
may be mistakenly interpreted as the addition of 1 to the address held inptr
. In fact the new memory address depends on the size in bytes of the pointer's target. This misunderstanding can lead to unexpected behaviour if sizeof is applied incorrectly."
So it all boils down to MISRA worrying about beginner programmers confusing ptr+1 to have the outcome we would have when writing (uint8_t*)ptr + 1
. The solution, in my opinion, is to educate the novice programmers, rather than to restrict the professional ones (but then if you hire novice programmers to write safety-critical software with MISRA compliance, understanding pointer arithmetic is probably the least of your problems anyhow).
Solve this by writing a permanent deviation from this rule!
If you for reasons unknown don't want to deviate, but to make your current code MISRA compliant, simply rewrite the function as
void Foo(uint8_t pu8Buffer[], uint16_t u16Len)
and then replace all pointer arithmetic with pu8Buffer[something]
. Then suddenly the code is 100% MISRA compatible according to the MISRA:2004 exemplar suite. And it is also 100% functionally equivalent to what you already have.
来源:https://stackoverflow.com/questions/19101587/pointer-to-array-of-bytes