
Passo 1 de 9
Localize os bits de uma máscara
Reconheça uma máscara hexadecimal como um mapa das posições de um byte que ela seleciona.
Trilha de aprendizado · Nível 9 · Tutorial 10
Manipule flags e campos de bits em variáveis e combine ou separe bytes, respeitando as promoções e os limites dos tipos do Uno R3.
Localize os bits de uma máscara
Reconheça uma máscara hexadecimal como um mapa das posições de um byte que ela seleciona. 2 min
Diferencie operações lógicas e bit a bit
Compare operadores que combinam padrões de bits com operadores que avaliam condições booleanas. 2 min
Considere as promoções antes de complementar
Entenda a promoção de `uint8_t`, o alcance do complemento e a limitação explícita de resultados antes de armazená-los em um byte. 3 min
Consulte flags sem alterar a variável
Use máscaras e comparação explícita com zero para consultar flags sem modificar a variável. 2 min
Ative, limpe e inverta bits selecionados
3 min
Desloque com segurança e construa máscaras
Construa máscaras de um bit com deslocamentos válidos, distinguindo a largura de unsigned int da faixa de um byte. 3 min
Leia um campo de bits
Isole um campo contíguo de um byte, alinhe-o ao bit zero e preserve o valor original. 2 min
Combine e recupere dois bytes
Componha uma palavra de 16 bits a partir de dois bytes e recupere exatamente os valores originais. 4 min
Aplicação final: confira as máscaras e os resultados
Resolva uma sequência integrada de manipulação de bits e confira limites, tipos, preservação de flags e recuperação de bytes. 4 min

Passo 1 de 9
Reconheça uma máscara hexadecimal como um mapa das posições de um byte que ela seleciona.
Um byte tem oito posições, numeradas de 0 a 7. A posição 0 é o bit menos significativo (à direita); a 7 é o mais significativo (à esquerda).
Uma máscara é um valor inteiro usado para marcar posições de interesse: cada bit em 1 seleciona sua posição correspondente. Por enquanto, apenas leia a máscara: ela não muda nenhuma variável sozinha.

Na máscara 0x81, os bits 7 e 0 estão em 1; portanto, essas são as posições selecionadas.
O prefixo 0x informa que o literal está em hexadecimal. O tipo uint8_t armazena os oito bits da máscara.
#include <stdint.h>
uint8_t extremos = 0x81; // bits 7 e 0 em 1
uint8_t centro = 0x3C; // bits 5, 4, 3 e 2 em 1Compare o padrão de oito bits com seu hexadecimal. Bits em 0 não são selecionados; bits em 1 são selecionados.
Por exemplo, 0x24 corresponde a 0010 0100: seleciona as posições 5 e 2. A máscara é somente um padrão de seleção; as operações que a aplicam serão estudadas depois.
Associe cada máscara às posições que ela seleciona.
Agora faça as associações.
Relacione cada literal às posições cujos bits valem 1.
Toque em um item e depois no par correspondente.
Complete a declaração com o literal que seleciona simultaneamente as posições 7 e 0 de um byte. Use o prefixo hexadecimal 0x.
Preencha a máscara hexadecimal.
#include <stdint.h>
uint8_t mascaraExtremos = ;
Passo 2 de 9
Compare operadores que combinam padrões de bits com operadores que avaliam condições booleanas.
Os operadores bit a bit trabalham posição por posição entre dois valores inteiros. Para cada coluna de bits, eles geram outro bit:
& resulta em 1 somente quando os dois bits são 1.| resulta em 1 quando pelo menos um bit é 1.^ resulta em 1 quando os bits são diferentes.Com a = 0x30 (00110000) e b = 0x0C (00001100), não há nenhuma posição em que ambos tenham 1. Portanto, a & b vale 0x00 — mesmo que a e b sejam valores não nulos.

Alinhe as posições antes de operar. Neste caso, 0x30 & 0x0C = 0x00, enquanto 0x30 | 0x0C = 0x3C e 0x30 ^ 0x0C = 0x3C.
Uma máscara indica quais posições importam no resultado. Se mascara tem 1 em uma posição:
valor & mascara mantém o bit de valor naquela posição; onde a máscara tem 0, o resultado fica 0.valor | mascara produz 1 naquela posição; onde a máscara tem 0, o resultado acompanha valor.valor ^ mascara produz o bit oposto naquela posição; onde a máscara tem 0, o resultado acompanha valor.Essas expressões produzem valores inteiros. Elas não são, por si só, perguntas verdadeiras ou falsas.
Compare o objetivo antes de escolher o operador.
| Expressão | Resultado | Uso |
|---|---|---|
| `a & b` | Padrão de bits inteiro | Combinar bits correspondentes |
| `a | b` | Padrão de bits inteiro | Combinar bits correspondentes |
| `a ^ b` | Padrão de bits inteiro | Marcar posições diferentes |
| `a && b` | `true` ou `false` | Exigir dois valores verdadeiros |
| `a || b` | `true` ou `false` | Aceitar ao menos um valor verdadeiro |
Compare os tipos de resultado destas duas intenções.
uint8_t a = 0x30;
uint8_t b = 0x0C;
uint8_t bitsEmComum = a & b; // 0x00
bool ambosSaoNaoNulos = a && b; // true
Em uma expressão bit a bit, os dois operandos são avaliados para que seus bits possam ser combinados. Já && e || usam curto-circuito:
testeA() && testeB(), se testeA() for falsa, testeB() não é chamada.testeA() || testeB(), se testeA() for verdadeira, testeB() não é chamada.Assim, não troque & por && apenas porque ambos lembram AND. Além de retornarem tipos de resultado diferentes, a execução das funções nos operandos pode mudar.
Nas duas primeiras linhas, as duas funções são chamadas. Nas demais, a segunda chamada depende do resultado da primeira.
bool testeA();
bool testeB();
bool padrao = testeA() & testeB(); // chama as duas
bool outroPadrao = testeA() | testeB(); // chama as duas
bool condicao1 = testeA() && testeB(); // pode pular testeB()
bool condicao2 = testeA() || testeB(); // pode pular testeB()
Dica
Use operadores lógicos para combinar condições de if. Use operadores bit a bit quando precisar obter ou rastrear um padrão de bits inteiro.
Complete cada expressão com o operador adequado. Depois, confira: comuns é 0x00; unidos e diferentes são 0x3C; as duas variáveis bool são verdadeiras.
uint8_t a = 0x30;
uint8_t b = 0x0C;
uint8_t comuns = a b;
uint8_t unidos = a b;
uint8_t diferentes = a b;
bool ambosNaoNulos = a b;
bool algumNaoNulo = a b;

Passo 3 de 9
Entenda a promoção de uint8_t, o alcance do complemento e a limitação explícita de resultados antes de armazená-los em um byte.
No Uno R3, uint8_t armazena 8 bits, mas, em uma expressão, ele é promovido a int. Isso ocorre porque o int de 16 bits da placa representa todos os valores de 0 a 255.
Assim, se byteValor contém 0x5A, a expressão ~byteValor complementa os 16 bits do int promovido. Considerando esses 16 bits, o padrão passa de 0x005A para 0xFFA5 — não apenas de 0x5A para 0xA5.
A variável original continua com 0x5A: ~ produz um resultado, mas não altera seu operando.

No Uno R3, o complemento atua sobre os 16 bits do valor promovido.
Use esta referência para rastrear o exemplo no Uno R3.
| Etapa | Tipo efetivo | Padrão em 16 bits |
|---|---|---|
| byteValor armazenado | uint8_t | 0x5A |
| Valor na expressão | int | 0x005A |
| Resultado de ~byteValor | int | 0xFFA5 |
~ e ! não são duas formas equivalentes de negar um valor.
~ complementa cada bit da largura efetiva da expressão e produz um padrão inteiro. Para 0x5A promovido no Uno R3, o padrão resultante é 0xFFA5 em 16 bits.! avalia logicamente o valor: produz false para qualquer valor diferente de zero e true para zero. Portanto, !0x5A é false.Quando a intenção for trabalhar explicitamente com um padrão sem sinal de 16 bits no Uno R3, use um operando unsigned int, como um literal com sufixo U. O literal 0x005AU é sem sinal; seu complemento tem o padrão 0xFFA5 nessa largura.
O sufixo U torna o literal sem sinal. No Uno R3, unsigned int tem 16 bits.
unsigned int padrao = ~0x005AU; // 0xFFA5 no Uno R3
bool vazio = !0x005AU; // falseAtenção
A largura efetiva depende da plataforma e dos tipos dos operandos. Neste tutorial, os exemplos usam o Uno R3, no qual int e unsigned int têm 16 bits. Não suponha que uma expressão terá a mesma largura em toda placa ou computador.
No Uno R3, uint8_t byteValor = 0x5A;. Qual descrição está correta para a expressão ~byteValor?
Qual operador produz uma condição lógica a partir de 0x5A?
Se o objetivo é guardar somente o byte invertido, limite primeiro o resultado largo aos oito bits inferiores. Com original = 0x5A, o complemento sem sinal é 0xFFA5; a máscara 0x00FFU produz 0x00A5. Só depois represente esse valor como uint8_t.
A conversão final escolhe a representação de destino. Ela não valida automaticamente a faixa, não reduz a largura da expressão anterior e não substitui uma limitação explícita quando ela faz parte da intenção do código.
Complete a máscara que mantém somente os oito bits inferiores antes da conversão para uint8_t.

Passo 4 de 9
Use máscaras e comparação explícita com zero para consultar flags sem modificar a variável.
Uma flag é um bit usado para representar um estado dentro de uma variável comum. Por exemplo, em estado, o bit 2 pode indicar que uma condição está ativa.
Para consultar uma flag, aplique a máscara com & e compare o resultado com zero:
(estado & mascara) != 0
A operação & produz um valor temporário. Ela não grava nada em estado; portanto, uma consulta não altera a variável.
Observe que somente a posição selecionada permanece no resultado temporário.

Se a posição selecionada está em 1, o resultado de estado & máscara é diferente de zero.
Use parênteses para tornar a intenção explícita: primeiro isole os bits com &; depois compare o resultado.
Neste exemplo, 0x04 seleciona o bit 2. Como estado vale 0x24, a consulta produz 0x04. Esse resultado não é 1, mas ainda é diferente de zero — logo, a flag está ativa.
Uma condição que consulta o bit 2 sem modificar estado.
#include <stdint.h>
uint8_t estado = 0x24;
const uint8_t FLAG_PRONTA = 0x04;
if ((estado & FLAG_PRONTA) != 0) {
// A flag está ativa.
}
// estado continua valendo 0x24.
Exemplo
Rastreamento: 0x24 & 0x04 resulta em 0x04. A condição verdadeira vem de 0x04 != 0, e não de uma comparação com 1.
Evite escrever estado & FLAG_PRONTA == 1: além de testar o valor errado para muitas máscaras, a expressão fica ambígua para leitura. Prefira sempre ((estado & FLAG_PRONTA) != 0).
Uma máscara também pode selecionar várias posições. Em uma condição como:
(estado & ALERTAS) != 0
a pergunta é: pelo menos um dos bits selecionados está ativo?
Se nenhum estiver ativo, o AND resulta em zero. Se um ou mais estiverem ativos, o resultado é diferente de zero. A variável original permanece igual nos dois casos.
As duas consultas usam a mesma máscara, mas produzem respostas diferentes conforme os bits do valor.

Uma máscara com várias posições responde se existe ao menos um bit selecionado em 1.
ALERTAS seleciona as posições 3 e 4. O resultado 0x10 confirma que pelo menos uma delas está ativa.
#include <stdint.h>
uint8_t estado = 0x52;
const uint8_t ALERTAS = 0x18;
if ((estado & ALERTAS) != 0) {
// Há pelo menos um alerta ativo.
}
// 0x52 & 0x18 resulta em 0x10.
// estado continua valendo 0x52.
Complete a condição que verifica FLAG_ERRO. Ela deve funcionar mesmo que o resultado isolado seja 0x20, e não 1.
#include <stdint.h>
uint8_t estado = 0x20;
const uint8_t FLAG_ERRO = 0x20;
if ((estado FLAG_ERRO) 0) {
// A flag está ativa.
}
Com estado = 0x24 e mascara = 0x04, qual resultado torna verdadeira a condição (estado & mascara) != 0?

Passo 5 de 9
Para ativar posições de uma máscara, use OR (|). Onde a máscara tem 1, o resultado fica em 1; onde ela tem 0, o bit original é preservado.
Exemplo: 0xB2 | 0x0C resulta em 0xBE.
0xB2 = 101100100x0C = 000011000xBE = 10111110Só os bits 3 e 2 mudaram. A máscara não determina o valor dos demais bits: eles continuam vindo de flags.

No OR, um zero na máscara deixa passar o bit original; um um força o resultado para um.
As duas formas abaixo atualizam a própria variável. A forma composta deixa explícita a intenção de modificar flags.
const uint8_t mascara = 0x0C;
flags = static_cast<uint8_t>(flags | mascara);
// Forma equivalente para atualização:
flags |= mascara;Para limpar posições, aplique AND (&) com a máscara complementada. Os 1 da máscara viram 0, forçando essas posições a zero; as outras posições devem receber 1 para serem preservadas.
No Uno R3, uint8_t é promovido a int em muitas expressões. Portanto, ~mascara não deve ser interpretado automaticamente como “o inverso de apenas oito bits”. Primeiro mantenha o cálculo em uma largura sem sinal e limite-o ao byte antes de converter.
Este padrão torna visíveis a largura intermediária e o limite de 8 bits antes do armazenamento em uint8_t.
const uint8_t mascara = 0x30;
const unsigned int manter =
~static_cast<unsigned int>(mascara) & 0x00FFU;
const unsigned int resultado =
static_cast<unsigned int>(flags) & manter;
flags = static_cast<uint8_t>(resultado);
// Forma composta, quando a máscara já representa
// apenas posições do byte:
flags &= static_cast<uint8_t>(manter);Dica
A conversão final para uint8_t representa o resultado no byte; ela não substitui a limitação explícita. Neste caso, & 0x00FFU garante que manter contenha somente os oito bits de interesse.
Para inverter flags, use XOR (^). Onde a máscara tem 1, o bit troca: 0 vira 1 e 1 vira 0. Onde a máscara tem 0, o bit fica igual.
Assim, flags ^= mascara; é apropriado para alternar estados selecionados. Não é uma operação de consulta: ela modifica flags.
Cada operação tem um efeito previsível sobre as posições selecionadas. Em todas elas, uma máscara limitada ao byte ajuda a manter claro quais posições podem mudar.
| Intenção | Expressão explícita | Forma composta | Efeito onde máscara = 1 |
|---|---|---|---|
| Ativar | flags | mascara | flags |= mascara | fica em 1 |
| Limpar | flags & ~mascara | flags &= ~mascara | fica em 0 |
| Inverter | flags ^ mascara | flags ^= mascara | troca 0 e 1 |
| Preservar | — | — | máscara = 0 preserva |
Complete os operadores para executar, nessa ordem, ativação, limpeza e inversão.
uint8_t flags = 0xB2;
const uint8_t ativar = 0x01;
const uint8_t limpar = 0x30;
const uint8_t inverter = 0x06;
flags ativar;
uint8_t aposAtivar = flags;
const unsigned int manter =
~static_cast<unsigned int>(limpar) & 0x00FFU;
const unsigned int limitado =
static_cast<unsigned int>(flags) manter;
flags = static_cast<uint8_t>(limitado);
uint8_t aposLimpar = flags;
flags inverter;
uint8_t aposInverter = flags;Depois de flags |= 0x01, qual é o valor de aposAtivar em hexadecimal?
Após a limpeza com a máscara 0x30, qual é o valor de aposLimpar em hexadecimal?
Depois de flags ^= 0x06, qual é o valor de aposInverter em hexadecimal?

Passo 6 de 9
Construa máscaras de um bit com deslocamentos válidos, distinguindo a largura de unsigned int da faixa de um byte.
Use um operando sem sinal para deixar explícita a largura em que o deslocamento ocorre. No Uno R3, unsigned int tem 16 bits. Em 1U << posicao, o literal 1U começa com um único bit em 1 e tem tipo unsigned int.
<< move os bits para a esquerda, insere zeros pela direita e descarta o que sair pela extremidade esquerda. Assim, 1U << 5 produz 0x0020. Com um operando sem sinal, >> move os bits para a direita, insere zeros pela esquerda e descarta os bits que saem à direita.
A operação acontece na largura efetiva do operando, não na largura da variável que talvez receba o resultado depois.

Os bits se movem dentro da largura efetiva do operando; os que saem dessa largura são descartados.
A contagem deve ser válida antes do deslocamento: ela não pode ser negativa e deve ser estritamente menor que a largura efetiva do operando.
No Uno R3, para 1U como unsigned int de 16 bits, as contagens de 0 a 15 são válidas para a operação. Logo, 1U << 8 é uma operação válida e produz 0x0100.
Mas uma máscara destinada a uint8_t tem outra regra: só pode selecionar posições de 0 a 7. Portanto, 1U << 8 é válido em 16 bits, porém não cabe em um byte e não representa uma máscara de byte.
Para construir uma máscara de byte a partir de uma posição informada, valide primeiro o objetivo específico: a posição deve estar entre 0 e 7. Só então execute 1U << posicao.
O U em 1U é importante: ele cria o ponto de partida como unsigned int. Se o operando à esquerda fosse um uint8_t, ele poderia ser promovido a int antes do deslocamento no Uno R3. Quando a intenção exigir uma largura sem sinal específica, converta o operando antes de deslocar; converter somente o resultado não muda a operação que já ocorreu.
Depois de validar 0 a 7, o resultado de 1U << posicao está entre 0x0001 e 0x0080, portanto cabe em uint8_t.
Bloco direto para criar uma máscara de byte. A variável começa com zero caso a posição seja recusada.
#include <stdint.h>
int posicao = 5;
uint8_t mascara = 0U;
if (posicao >= 0 && posicao <= 7) {
unsigned int resultado = 1U << posicao;
mascara = static_cast<uint8_t>(resultado);
}
// Para posicao = 5, mascara vale 0x20.
Atenção
Uma conversão posterior para uint8_t não corrige uma operação inválida. Por exemplo, 1U << 16 é inválido no Uno R3 porque 16 não é menor que a largura de 16 bits de unsigned int. Também não execute um deslocamento com contagem negativa.
A regra posicao <= 7 é ainda mais restritiva: ela protege a finalidade de criar uma máscara de byte. Ela rejeita a posição 8 mesmo que 1U << 8 seja válido em 16 bits.
Complete a recusa das posições que não pertencem a um byte e o literal usado para iniciar a máscara.
#include <stdint.h>
int posicao = 7;
uint8_t mascara = 0U;
if (posicao || posicao ) {
// Posição recusada: mascara continua em 0.
} else {
unsigned int resultado = << posicao;
mascara = static_cast<uint8_t>(resultado);
}
No Uno R3, classifique as posições para a expressão 1U << posicao quando o objetivo final é produzir uma máscara de uint8_t. Qual alternativa está correta?

Passo 7 de 9
Isole um campo contíguo de um byte, alinhe-o ao bit zero e preserve o valor original.
Um campo de bits é um grupo de posições contíguas que guarda um pequeno valor dentro de uma variável. Para lê-lo, use duas etapas sem alterar o byte original:
Considere status = 0xB4, ou 10110100 em oito bits. Vamos interpretar as posições 5, 4 e 3 como um campo de três bits. A máscara 0x38U seleciona exatamente essas posições.
Depois de isolar o campo, seu padrão ainda está nas posições 5 a 3. O deslocamento de três posições o alinha à posição 0, permitindo lê-lo como um número de 0 a 7.

A máscara isola o campo; o deslocamento à direita transforma sua posição em valor numérico.
No Uno R3, um uint8_t pode ser promovido para int em uma expressão. Para deixar explícito que o isolamento e o deslocamento devem usar um tipo sem sinal, converta o valor para uint16_t antes dessas operações.
A máscara produz 0x30: os bits externos ao campo se tornam zero. Em seguida, 0x30 >> 3 resulta em 0x06, isto é, o valor decimal 6.
O campo tem apenas três bits, portanto seu resultado está entre 0 e 7. Só então é seguro representá-lo em uint8_t. Note que status não recebe nenhuma atribuição: ele continua sendo 0xB4.
Exemplo de extração das posições 5, 4 e 3 de um byte.
#include <stdint.h>
const uint8_t status = 0xB4U; // 10110100
const uint16_t isolado =
static_cast<uint16_t>(status) & 0x38U;
const uint8_t modo =
static_cast<uint8_t>(isolado >> 3);
// status = 0xB4; isolado = 0x30; modo = 6O diagrama mostra um campo nas posições 5, 4 e 3 do byte 0xB4. Complete o código para isolá-lo, alinhá-lo ao bit 0 e registrar o valor previsto. Não há atribuição a status, portanto o byte de origem deve permanecer preservado.
Preencha a máscara, a quantidade de deslocamento e o valor extraído.
#include <stdint.h>
const uint8_t status = 0xB4U;
const uint16_t isolado =
static_cast<uint16_t>(status) & ;
const uint8_t modo =
static_cast<uint8_t>(isolado >> );
const uint8_t previsto = ;
Passo 8 de 9
Componha uma palavra de 16 bits a partir de dois bytes e recupere exatamente os valores originais.
Uma palavra uint16_t tem 16 bits. Para reunir dois uint8_t, trate um como byte mais significativo (alto) e o outro como byte menos significativo (baixo):
alto ocupará as posições 15 a 8.baixo ocupará as posições 7 a 0.Exemplo: alto = 0xA5 e baixo = 0x3C formam a palavra 0xA53C.
Isso descreve o valor da variável. Não informa nem depende de como bytes podem estar dispostos na memória física.

O byte alto ocupa os oito bits superiores; o byte baixo ocupa os oito bits inferiores.
No Uno R3, converta alto para uint16_t antes de deslocá-lo oito posições. Assim, o deslocamento atua sobre um operando sem sinal de 16 bits, em vez de depender da promoção de uint8_t para int.
Depois, use OR para unir as regiões que não se sobrepõem. Também convertemos baixo para uint16_t, deixando os dois operandos do OR na mesma largura explícita.
Para recuperar os valores, mantenha somente os oito bits inferiores ou desloque os oito superiores para a direita. A máscara 0x00FFU confirma que o resultado está entre 0x00 e 0xFF; só então ele é convertido para uint8_t. Nenhuma dessas operações altera palavra.
Composição e recuperação de dois bytes
#include <stdint.h>
uint8_t alto = 0xA5;
uint8_t baixo = 0x3C;
uint16_t palavra =
(static_cast<uint16_t>(alto) << 8) |
static_cast<uint16_t>(baixo);
uint8_t baixoRecuperado =
static_cast<uint8_t>(palavra & 0x00FFU);
uint8_t altoRecuperado =
static_cast<uint8_t>((palavra >> 8) & 0x00FFU);Confira a ida e a volta em hexadecimal. Os casos 0x80 e 0xFF no byte alto confirmam que o bit 7 desse byte é preservado quando passa à posição 15 da palavra.
| alto | baixo | palavra | alto recuperado | baixo recuperado |
|---|---|---|---|---|
| 0x00 | 0x00 | 0x0000 | 0x00 | 0x00 |
| 0xA5 | 0x3C | 0xA53C | 0xA5 | 0x3C |
| 0x80 | 0x01 | 0x8001 | 0x80 | 0x01 |
| 0xFF | 0x7E | 0xFF7E | 0xFF | 0x7E |
Ordene as ações indispensáveis para compor uma palavra a partir de alto e baixo. A última ação já inclui a conversão de baixo.
Complete a composição e a extração para formar 0x8001 e recuperar 0x80 e 0x01. A primeira lacuna deve ser uma conversão que resulte em código válido antes de (alto).
uint8_t alto = 0x80;
uint8_t baixo = 0x01;
uint16_t palavra = ((alto) << 8)
static_cast<uint16_t>(baixo);
uint8_t baixoRecuperado =
static_cast<uint8_t>(palavra & 0x00FFU);
uint8_t altoRecuperado =
static_cast<uint8_t>((palavra 8) & 0x00FFU);Com alto = 0xFF e baixo = 0x7E, qual deve ser o valor de palavra em hexadecimal?

Passo 9 de 9
Resolva uma sequência integrada de manipulação de bits e confira limites, tipos, preservação de flags e recuperação de bytes.
Nesta aplicação final, você vai prever e conferir uma sequência completa usando apenas variáveis comuns.
Antes de aceitar um resultado, percorra esta lista:
1U?uint8_t, quando necessário?Uma conversão posterior não torna válido um deslocamento que já era inválido.

A máscara altera ou seleciona apenas as posições previstas; a conferência compara os bits externos antes e depois.
Dica
Faça a previsão antes de executar o código:
inicial = 0x25 e a máscara do bit 7, a ativação produz 0xA5.0xA5 & 0x7F resulta em 0x25.0xA5, o campo selecionado por 0x38, deslocado três posições à direita, vale 0x04.1U << 8 seja válido para unsigned int de 16 bits no Uno R3, ele não representa uma máscara que caiba em uint8_t.Copie este sketch para a IDE Arduino apenas se quiser fazer a conferência local. Ele usa somente o LED integrado: após a gravação, o LED fica aceso quando todas as comparações são verdadeiras.
#include <stdint.h>
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
const uint8_t inicial = 0x25;
const uint8_t posicao = 7;
const uint8_t posicaoInvalida = 8;
bool posicaoValida = (posicao < 8U);
bool rejeitouInvalida = (posicaoInvalida >= 8U);
uint8_t flags = inicial;
uint8_t mascara = 0U;
if (posicaoValida) {
unsigned int resultado = 1U << posicao;
mascara = static_cast<uint8_t>(resultado);
flags = static_cast<uint8_t>(
static_cast<unsigned int>(flags) |
static_cast<unsigned int>(mascara));
}
bool flagsCorretas = (flags == 0xA5U);
bool externosPreservados =
((flags & 0x7FU) == (inicial & 0x7FU));
uint8_t campo = static_cast<uint8_t>(
(static_cast<uint16_t>(flags) & 0x0038U) >> 3);
bool campoCorreto = (campo == 0x04U);
const uint8_t alto = 0xA5;
const uint8_t baixo = 0x3C;
uint16_t palavra =
(static_cast<uint16_t>(alto) << 8) |
static_cast<uint16_t>(baixo);
uint8_t altoRecuperado = static_cast<uint8_t>(
(palavra >> 8) & 0x00FFU);
uint8_t baixoRecuperado = static_cast<uint8_t>(
palavra & 0x00FFU);
bool bytesRecuperados =
(altoRecuperado == alto) && (baixoRecuperado == baixo);
bool tudoCerto = posicaoValida && rejeitouInvalida &&
flagsCorretas && externosPreservados &&
campoCorreto && bytesRecuperados;
digitalWrite(LED_BUILTIN, tudoCerto ? HIGH : LOW);
}
void loop() {
}
Após compilar e gravar sem alterações no Arduino Uno R3: LED integrado: aceso continuamente
O sketch não envia texto ao computador. A saída observável é o estado do LED integrado: aceso indica que todas as comparações programadas passaram; apagado indica que alguma comparação falhou ou que o código foi alterado.
No Uno R3, o byte alto é convertido para uint16_t antes de << 8. Portanto, o deslocamento ocorre sobre um operando sem sinal de 16 bits, e deslocar oito posições é válido.
O sketch também não constrói máscara para posicaoInvalida = 8: ele apenas confirma que esse valor deve ser rejeitado para a finalidade de um byte. Se você executar a prática, LED aceso confirma as comparações programadas; LED apagado indica que alguma expectativa não foi satisfeita.
Complete a função para recusar posições que não pertencem a um byte antes de construir a máscara.
uint8_t mascaraDeBit(uint8_t posicao) {
if (posicao ) {
return 0U;
}
return static_cast<uint8_t>( << posicao);
}Use esta tabela como rastreamento da sequência. A composição usa alto = 0xA5 e baixo = 0x3C.
| Etapa | Expressão ou valor | Resultado |
|---|---|---|
| Máscara do bit 7 | 1U << 7 | 0x0080 |
| Ativação | 0x25 | 0x80 | 0xA5 |
| Bits externos | 0xA5 & 0x7F | 0x25 |
| Campo | (0xA5 & 0x38) >> 3 | 0x04 |
| Composição | 0xA5 << 8 | 0x3C | 0xA53C |
| Byte alto | (0xA53C >> 8) & 0x00FF | 0xA5 |
| Byte baixo | 0xA53C & 0x00FF | 0x3C |
Justifique em poucas frases: por que a posição 8 é rejeitada para uma máscara de byte e por que alto é convertido para uint16_t antes de << 8? Inclua os dois bytes recuperados da palavra 0xA53C.
Escreva pelo menos 80 caracteres (0/80).
Resumo
1U e confira a largura efetiva do operando.uint16_t antes de deslocá-lo por oito posições.Parabéns! Você concluiu: Máscaras e operações de bits em C/C++
Você concluiu este nível!
Agora você vai iniciar: Firmware temporizado e periféricos
Temporização não bloqueante com millisControlar duas sequências de LEDs com intervalos independentes no Uno R3 próprio, mantendo o fluxo principal disponível e tratando corretamente o retorno da contagem de millis.Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks