MISRA Discussion Forums

Full Version: Rule 17.4 - can I reference to an array, inside a struct?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I want to define a list of actions in ROM, so it cannot get corrupted. An array of struct, in ROM, where each struct contains enough information to define what the MCU should do.

One of the actions is to read some info from an exernal device. So it needs to go into a buffer, and the buffer is obviously in RAM.

The problem I have is, how do I make a typedef for a struct, where one member of the struct is a reference to the buffer? I will need to use the buffer as an array, and referring to an array element by index is of course not allowed, if a pointer type is used for the array.
Code:
typedef s_SomeStruct
{
  uint8_t *buf;  /* not ok, because SomeStruct.buf[x] will not be compliant */
  size_t bufsize;
} TSomeStruct;
But I cannot find a way to use an array type. For function parameters, I could have foo(uint8_t buf[]) but it's not going to compile in a structure definition
Code:
typedef s_SomeStruct
{
  uint8_t buf[]; /* you wha'? */
  size_t bufsize;
} TSomeStruct;
Is there a known way around this, other than creating a deviation?

Thanks

Frank
For MISRA-C:2004, a strict interpretation of the Rule 17.4 provides you with two options
  • Raise a deviaion
  • Define and use as an array pointer (see below)

Code:
typedef unsigned char uint8_t;
typedef struct s_SomeStruct
{
  uint8_t (*pbuf)[];
  size_t bufsize;
} TSomeStruct;

#define BUFSIZ 10

extern uint8_t buf[ BUFSIZ ];
const TSomeStruct s = { &buf, BUFSIZ }

void main( void )
{
  ...
  (*s.pbuf)[5] = 10u;    /* Example of buffer access */
  ...
}

For MISRA C:2012 this rule has been refined and retargetted as Rule 18.4 to define allowable pointer arithmetic. This would allow what you want to do!
Thanks.

I think it'll have to be a deviation then. There will be several instances of this struct, and the array size is not the same in all of them.

I could declare an array type large enough to hold the largest array I would want to point at, and use a pointer to that, but that strikes me as less safe rather than more as it would tempt me to place some confidence on the array size declared in the type, as opposed to the size specified in the struct.

Frank
In the example given by misra-c, the size of the array is not specified by the definition of the struct TSomeStruct. The size of the array buf is assigned to the object s at compile time. You can have as many objects of this struct type as you want and initialise them as you see fit.

Dave B.
Aargh, you are quite right and I was stupid.

Ok, I think that's the syntax I need. Thanks to both of you.

Now the only problem is that PC-lint doesn't like the & in
const TSomeStruct s = { &buf, BUFSIZ };
(Warning 545: Suspicious use of &) but that'd be something for the GImpel website, not here.

So thanks again

Frank
You're welcome!

Please post back how you get on with Gimpel. As I recall from the history of the languages development, the concept of array types was added some what belatedly (during standardisation) and as a consequence it had to retain backwards compatibility, which is why it has mostly gone unnoticed. Also, in those earlier pre-standardisation versions of C, taking the address (& operator) of something that was an address, such as a function identier or an array identifier was undefined, but generally accepted as being benign and resulted in the identifiers address. This I believe is what PC Lint is trying to tell you. (May be.) But this is inconsistent with Standard C for array types and they should reconsider their check (which may still be fair for function and non-array object identifiers).

Dave B.
Sorry about the late reply, I have been away from this code for a long time, due to being put on more urgent projects. Now I'm back to it, and I have my code working, using the declarations recommended above.

The Lint message was a warning, not an error, and says the usage was "suspicious", not wrong. Gimpel's documentation says that taking the address of an array name (which is itself an address, as you say) used to be officially illegal, as opposed to benign. But it goes on to say

Quote:...given
int a[10];
int (*p) [10];
Then a and &a, as pointers, both represent the same bit pattern, but whereas a is a pointer to int, &a is a pointer to an array of 10 integers. Of the two only &a may be assigned to p without complaint. If you are using the & operator in this way, we recommend that you disable this message.

So I think adding the directive to suppress this warning to std.lnt is the correct thing to do here, and that is what I have done.

Thanks again

Frank