Anotando estruturas e classes

Você pode anotar structs e membros de classe usando anotações que agem como invariáveis, presume-se que elas sejam verdadeiras em qualquer chamada de função ou entrada/saída de função que envolva a estrutura delimitante como um parâmetro ou um valor de resultado.

Anotações de classe e struct

  • _Field_range_(low, high)

    O campo está no intervalo (inclusivo) de low até high. Equivalente à _Satisfies_(_Curr_ >= low && _Curr_ <= high) aplicada ao objeto anotado usando as pré ou pós condições apropriadas.

  • _Field_size_(size), _Field_size_opt_(size), _Field_size_bytes_(size), _Field_size_bytes_opt_(size)

    Um campo que tem um tamanho gravável em elementos (ou bytes), conforme especificado por size.

  • _Field_size_part_(size, count), _Field_size_part_opt_(size, count), _Field_size_bytes_part_(size, count), _Field_size_bytes_part_opt_(size, count)

    Um campo que tem um tamanho gravável em elementos (ou bytes), conforme especificado por size, e a count desses elementos (bytes) que são legíveis.

  • _Field_size_full_(size), _Field_size_full_opt_(size), _Field_size_bytes_full_(size), _Field_size_bytes_full_opt_(size)

    Um campo que tem um tamanho legível e gravável em elementos (ou bytes), conforme especificado por size.

  • _Field_z_

    Um campo que tem uma cadeia de caracteres terminada em nulo.

  • _Struct_size_bytes_(size)

    Aplica-se à declaração de classe ou struct. Indica que um objeto válido desse tipo pode ser maior que o tipo declarado, com o número de bytes sendo especificado por size. Por exemplo:

    
    typedef _Struct_size_bytes_(nSize)
    struct MyStruct {
        size_t nSize;
        ...
    };
    
    

    O tamanho do buffer em bytes de um parâmetro pM de tipo MyStruct * é então usado para ser:

    min(pM->nSize, sizeof(MyStruct))
    

Exemplo

#include <sal.h>

// This _Struct_size_bytes_ is equivalent to what below _Field_size_ means.
_Struct_size_bytes_(__builtin_offsetof(MyBuffer, buffer) + bufferSize * sizeof(int))
struct MyBuffer
{
    static int MaxBufferSize;

    _Field_z_
    const char* name;

    int firstField;

    // ... other fields

    _Field_range_(1, MaxBufferSize)
    int bufferSize;

    _Field_size_(bufferSize)        // Preferred way - easier to read and maintain.
    int buffer[]; // Using C99 Flexible array member
};

Anotações para este exemplo:

  • _Field_z_ é equivalente a _Null_terminated_. _Field_z_ para o campo de nome, especifica que o campo de nome é uma cadeia de caracteres terminada em nulo.
  • _Field_range_ para bufferSize especifica que o valor de bufferSize deve estar entre 1 e MaxBufferSize (ambos inclusivos).
  • Os resultados finais das anotações _Struct_size_bytes_ e _Field_size_ são equivalentes. Para estruturas ou classes que têm um layout semelhante, _Field_size_ é mais fácil de ler e manter, pois tem menos referências e cálculos do que a anotação equivalente _Struct_size_bytes_. _Field_size_ não requer conversão para o tamanho do byte. Se o tamanho do byte for a única opção, por exemplo, em um campo de ponteiro vazio, _Field_size_bytes_ poderá ser usado. Se _Struct_size_bytes_ e _Field_size_ existirem, ambos ficarão disponíveis para ferramentas. Caberá à ferramenta decidir o que fazer se as duas anotações discordarem.

Confira também