Algumas particularidades sintáticas de C99

C99

Frequentemente vejo alguns amigos desenvolvendo em C e sempre se deparam com algumas construções que são completamente “esquisitas”. O esquisito está entre aspas pois são construções que não são válidas em ANSI C (ou no nosso bom e velho amigo C89) e completamente válidas em C99.

Em artigos anteriores eu utilizei algumas construções não muito usuais, e que gosto muito: inicialização de estruturas, de vetores e compound literals. Como os compiladores ANSI C utilizados em sistemas embarcados já provém suporte ao C99, nada como explorar isso e ver como tirar mais proveito do compilador.

Inicialização de vetores

Em C89 a inicialização dos elementos de vetores é em ordem fixa, respeitando a ordem dos elementos no vetor. Já em C99, especificando o elemento do vetor o qual queremos inicializar, podemos inicializá-lo em qualquer ordem. Para inicializar um elemento de vetor em C99, escreva ‘[índice] =’ antes do valor do elemento, por exemplo: 

A construção acima é equivalente à inicialização a seguir em C89: 

Repare que os termos não inicializados explicitamente são inicializados com zero.

Inicialização de estruturas

Em C89 você pode inicializar uma estrutura assim: 

O detalhe aqui é que os elementos devem ser inicializados na mesma ordem que eles são listados na declaração da struct: 

Assim, quando declaramos uma variável do tipo struct STGpioOutputConfig, dwSYSCTL vem primeiro,  dwBase depois e assim por diante. Isso pode ser um inconveniente pois como todo código de inicialização não é alterado nunca, todo código dependente da ordem dos inicializadores pode não funcionar mais. Em C99 você pode inicializar uma estrutura especificando os nomes dos elementos da struct:

Esta construção não somente desacopla a ordem dos inicializadores, mas torna o código mais legível. Como benefício adicionado, os elementos não inicializados são inicializados com zero (0). Como facilidade, se durante o projeto qualquer campo for adicionado à estrutura, a sua inicialização pode ser acrescentada sem medo de que os outros elementos da estrutura tenham o valor de inicialização alterados.

Neste ponto vou indicar uma forma de organização de projetos que utilizo frequentemente, que é a inicialização de vetores de estruturas de tal forma a representar algum aspecto de implementação. Repare que o vetor de estruturas declarado acima, stUserLedCfg, é a representação de vários LEDs presentes em um projeto. Dependendo do tamanho do projeto pode ser um pouco difícil de lembrar qual elemento do vetor representa um dado led. Assim, sempre que possível, declaro uma enumeração que cobre a faixa de elementos do vetor e, na  inicialização, inicializo cada elemento explicitamente. Para o vetor de estrutura citado, ficaria assim:

Com esta construção fica muito mais fácil de organizar o código e ele se torna totalmente extensível.

Compound literals em atribuição a estruturas

Esta nova sintaxe de inicialização de estruturas é fabulosa, mas não ajuda em tudo. Vamos a um exemplo prático: necessitamos inicializar uma estrutura qualquer, por exemplo, a GPIO_InitTypeDef presente na STDPeripheralLib da ST. Em C89, teríamos algo assim:

Usando a construção de C99 chamada compound literal, você pode atribuir valores para a struct initGPIO da forma apresentada abaixo:

Tenha em mente que esta construção sempre emprega uma declaração anônima. Debaixo do capô, o compilador faz algo do tipo:

Novamente, a coisa legal aqui é que os elementos não inicializados explicitamente são inicializados com zero.

Com a mesma construção, é possível inicializar uma struct com zero somente com a seguinte declaração:

Compound literals com primitivas

Compound literals também podem ser aplicadas a primitivas. Em geral, a declaração abaixo não tem muita utilidade: 

Porém, devido ao compound literal estar associado a uma variável anônima, podemos usar o endereço dela:

Podemos aplicar isso em exemplos do tipo abaixo, que é uma construção C89:

A mesma construção poderia ser feita em C99 da forma mostrada abaixo:

Conclusão – C89 vs C99

Enquanto C99 possui alguns updates em relação ao padrão C89, é interessante habilitá-lo em seu compilador e começar a usar. O seu uso tornará as suas implementações mais legíveis e portáveis. Além disso, atente-se à documentação do seu compilador, pois podemos ter alguns ganhos de velocidade ou de uso de memória se utilizarmos compound literals e outras construções de C99.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Software » Algumas particularidades sintáticas de C99
Comentários:
Notificações
Notificar
guest
3 Comentários
recentes
antigos mais votados
Inline Feedbacks
View all comments
JonnyDoin
JonnyDoin
08/10/2016 07:07

Dias, excelente artigo! Compound literals são um dos aspectos menos explorados do C99, e permitem construções de alto nível, com declaração no ponto-de-uso. Um dos aspectos que mais gosto em compound literals é o uso de pointers para structs como passagem de parâmetros em funções. Neste caso, o uso de compound literals permite a especificação de named parameters, similar a linguagens mais estruturadas (como ADA, por exemplo). Esta construção é C99: // SECURE_STATUS_T ecdsa_verify(ECDSA_VECTOR_T *vector, ECDSA_CMD_EVENT_T *event); SECURE_STATUS_T ret = ecdsa_verify( &(ECDSA_VECTOR_T){ .key_type = ECC_KEY_SYS_MASTER, // master public key .msg_hash = ecdsa.msg_hash, // ptr to the 32bytes sha-256 message hash… Leia mais »

Eduardo Gomes
Eduardo Gomes
03/10/2016 11:54

Muito esclarecedor. Parabéns pelo artigo!

Rafael Dias
Rafael Dias
Reply to  Eduardo Gomes
03/10/2016 20:01

obrigado, Mestre!

Talvez você goste:

Séries

Menu