This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Confusing definition

C:\Nordic Semiconductor\nrf51_sdk_v4_4_1_31827\nrf51822\Include\ble\softdevice\ble_gatts.h


typedef struct {
  uint16_t     handle;    /**< Attribute Handle. */
  uint8_t       op;          /**< Type of write operation, see @ref BLE_GATTS_OPS. */
  ble_gatts_attr_context_t    context;     /**< Attribute Context. */
  uint16_t      offset;      /**< Offset for the write operation. */
  uint16_t      len;          /**< Length of the incoming data. */
  uint8_t       data[1];    /**< Incoming data, variable length. */
} ble_gatts_evt_write_t;

My question is how to interpret the element data[1]? Is it just uint8_t *data(C-wise it is)? If so why is it defined in such a way? Especially with the size of the data array as one with the following comment about its variable length which all together makes this definition very confusing.

Thanks.

  • I'm trying to response as soon as I can to beat the time difference, so excuse me it is little bit aster 6 in the morning here... Your said:"Beware that you are never expected to initialize a struct of this type, as it's only an event structure". There is option static winch forces a compiler to initialize memory with 0 and yes this is static and not dynamic memory. That is exactly what SD is doing. BTW please mention the exact type: we're talking about quite few in this discussion.

    http://c-faq.com/struct/structhack.html char data[] is defined in C99 and not in C89 as you said before. char data[1] is defined in both standards. Yet it is very tastefulness to use [1] as commenting it as variable length. In this case adding extra pointer and all hassles which come with it is much better for readability. It worth it from my stand point especially if this code is published for other people reading/using. Don't see any issues with static allocation by SD array of MAX_MTU size and application casting it to the any type it knows and needs.

    Thank you for coming back to this discussion.

  • "in my opinion whether that's any clearer is mostly a matter of taste, when most of this array may very well be uninitialized memory." I'm always applying the rule: clearly define the object and use it's definition. In other words in my application expects a message it needs to know how to interpret it. So typedef enum { MON, TUE, WED, THU, FRI, SAT, SUN } my_app_t is much better than uint8_t week_day; And when the message structure is typedef struct { my_app_t begin; my_app_t end; } my_msg_t; I'd verify that len is == sizeof(my_msg_t) and then will use it as data->begin and data->end and not data[0] and data[1] and getting warning about data[1]... BTW Warnings should be strictly prohibited - compiler doesn't understand your intent and therefore such code is not portable even if it is correct for particular case.

    Isn't if clear and very readable?!

    uint8_t

  • "I'm a little unsure why you found my answer worthy a down-vote, though, as I seriously tried to explain why this was there and what it means."

    1. This is mostly result of my frustration and I did instantly try to remove but a) I'm not smart enough to figure out how to do so, b) this website doesn't allow to.
    2. I was unhappy with your intent to explain me C and not the subject of the matter. If you will this is sort of religious war between software professionals and electrical engineers who are writing code... Software people are trained always to write code that not only works but it is portable, warning free, readable and clear how it does so when EE guys are usually stopping with "it works now" and maybe adding some comments...
    3. I'm sorry if in any way offended you.
  • I'm not sure I understand what you mean about static declarations. My point was that application code should not need to ever declare a variable of this type (although possibly a pointer to one).

    Unfortunately, I don't think we'll ever fully agree on what is most readable and not here, but I've added a request internally to consider this question again, either adding a more extensive comment or possibly also change the declaration to [], to indicate that the length is in fact unknown at compile time.

  • I'm wasn't offended, but I find it strange to downvote an answer, not because it's wrong, but because you personally disagree with it. Even when re-reading your original question and my answer, I honestly think I've answered the exact questions you were raising.

    Since I don't know a lot about your proficiency with C, I found it appropriate to include some pointers for further information in case my explanation wasn't clear. This may also be useful for other people that later may find this question.

    I do agree with your general intentions of writing clear code, it's just that we disagree on whether this particular definition is clear or not. Using a well-established pattern, even though an apparently slightly controversial one, is normally exactly what I'd say is a good solution.

    Warnings should of course always be avoided, and that something works is in itself no excuse for having out-of-spec code, it's just that this snippet in question is not out-of-spec.

    I'm not going to go further into your try to make this a discussion on education and profession, but I can assure you that most people working in our software department are properly educated software engineers.

Related