Alterar um byte de uma variavel long

Qual a melhor maneira de alterar apenas um byte de uma variável long de 4 bytes ?
Exemplo. Como alterar o terceiro byte sem mexer nos demais ?

usar operações bit a bit

unsigned long v = 123456;
v |= 0bxxxxxxxx000000; // use x = 1 para forçar esses bits a 1, 0 para manter o bit inalterado
v &= 0byyyyyyyy11111111; // use y = 0 para forçar esses bits a 0, 1 para manter o bit inalterado

você também pode usar um ponteiro de byte para a variável, modificar a memória e, em seguida, memcpy() em uma variável para o resultado

unsigned long v = 123456;
unsigned long result;
unsigned long * ptr = &v;
ptr[2] = 0bxxxxxxxx; // modifique o terceiro byte (o índice começa em 0). lembre-se que o GCC usa little endian para representar os dados na memória
memcpy(&result, ptr, sizeof result); // https://cplusplus.com/reference/cstring/memcpy/

Interessante.

Em PicBasic seria operação muito simples:
V.byte[2] = novovalor.

No seu exemplo por mascaramento teria como fazer em hexadecimal ?

void setup() {
  Serial.begin(115200);
  unsigned long v = 0xDE00BEEF;
  v |= 0x00AD0000; 
  Serial.print("v = 0x"); Serial.println(v, HEX);
}

void loop() {}

sketch.ino - Wokwi ESP32, STM32, Arduino Simulator

1 Like

Isso modifica a variável mas nesse exemplo eu tenho de escreve-lo diretamente.
Eu preciso que o novo byte seja dinâmico, que eu possa manipulá-lo separadamente antes de inserir na variável - que ele possa ser representado por uma variável separada.
O exemplo com memcpy e com o ptr[2] não funcionou.
O ideal seria algo como bitWrite() mas que fosse com bytes e não bits

uint32_t v = 0xDE00BEEF;

void setup() {
  Serial.begin(115200);
  uint8_t x = 0xAD;
  // modificação direta de bytes
  uint8_t * ptr = (uint8_t *) &v;
  ptr[2] = x;
  Serial.print("Result = 0x"); Serial.println(v, HEX);

  // ou se você tivesse um buffer de bytes, deseja mover para o uin32_t
  uint32_t r;
  memcpy(&r, ptr, sizeof r);
  Serial.print("Result = 0x"); Serial.println(r, HEX);
}

void loop() {}

Ok. Agora funcionou . Obrigado pelo help.

Já pensaste em uniões?

union LongBytes {
   unsigned long ulong ; 
   unsigned char uchar[4]; 
} data; 

data.ulong = 50; //escrever na variável ulong. 
data.uchar[1] = 20; //escrever no segundo byte da variável. 

É apenas mais uma maneira, não muito comum, de mexer com a memória.

não está correto em C++ se você tentar ler do outro elemento

It's undefined behavior to read from the member of the union that wasn't most recently written. Many compilers implement, as a non-standard language extension, the ability to read inactive members of a union.

(Union declaration - cppreference.com)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.