Combinando dos uint8_t como uint16_t

3 minutos de lectura

avatar de usuario
johan

tengo los siguientes datos

uint8_t d1=0x01; 
uint8_t d2=0x02; 

Quiero combinarlos como uint16_t como

uint16_t wd = 0x0201;

¿Cómo puedo hacerlo?

Puede utilizar operadores bit a bit:

uint16_t wd = ((uint16_t)d2 << 8) | d1;

Porque:

 (0x0002 << 8) | 0x01 = 0x0200 | 0x0001 = 0x0201

  • Sí, lo es. d2 primero debe emitirse (de lo que se ocupa la publicación editada).

    –Jonathan Grynspan

    6 de marzo de 2013 a las 14:26

  • @LuchianGrigore: Oh, sí, lo he olvidado. Gracias.

    – md5

    6 de marzo de 2013 a las 14:26


  • @LuchianGrigore & JonathanGrynspan No necesariamente, ya que d2 primero es ascendido a int (que es al menos 16 bits). Pero bien, todavía podría ser UB si int en realidad era solo 16 bits en su plataforma y (int)d2 << 8 desbordaría el no negativo int rango.

    – Christian Raú

    06/03/2013 a las 14:30


  • No veo cómo el elenco mejoraría algo. Supongamos que uint16_t tiene un rango de conversión más bajo que int, entonces no ha resuelto nada con el elenco, el operando izquierdo aún se promovería implícitamente a (firmado) int. Pero como no hay forma de que pueda arrojar un valor negativo, el comportamiento de este código y el original siempre está bien definido.

    – Lundin

    6 de marzo de 2013 a las 14:31

  • Mi respuesta también se encarga de eso.

    – R.. GitHub DEJA DE AYUDAR A ICE

    6 de marzo de 2013 a las 14:31

La forma más sencilla es:

256U*d2+d1

  • Oh Ahora realmente tenemos un caso de uso para las operaciones bit a bit y todavía te apegas a la aritmética aburrida. 😉

    – Christian Raú

    6 de marzo de 2013 a las 14:33

  • <<8 y *256 son operaciones idénticas, excepto que la primera tiene un comportamiento indefinido en más casos y, por lo tanto, generalmente no es deseable. Casi nunca hay una razón para usar el << o >> operadores a menos que el operando de la derecha sea variable (en cuyo caso tiene un buen operador de exponenciación).

    – R.. GitHub DEJA DE AYUDAR A ICE

    6 de marzo de 2013 a las 14:39

  • Sí, ese comentario fue de naturaleza bastante humorística.

    – Christian Raú

    06/03/2013 a las 14:40

  • ¿Cómo funciona esta clasificación de respuestas? ¿Por qué esto siempre aparece en la parte inferior de la página?

    – Brett Hale

    14 de abril de 2016 a las 10:22

avatar de usuario
Lundin

Esto es bastante simple. No necesitas moldes, no necesitas variables temporales, no necesitas magia negra.

uint8_t d1=0x01; 
uint8_t d2=0x02; 
uint16_t wd = (d2 << 8) | d1;

Este siempre es un comportamiento bien definido ya que d2 siempre es un valor positivo y nunca se desborda, siempre que d2 <= INT8_MAX.

(INT8_MAX se encuentra en stdint.h).

  • … excepto cuando es no 0x7F (ver 5.2.4.2)

    – autista

    6 de marzo de 2013 a las 14:53

  • @modifiablelvalue Énfasis en en la práctica. Todas las implementaciones sanas usan wchar_t para números enteros más grandes si esa es su preocupación. Si su preocupación es el complemento de uno o las CPU de signo y magnitud, ¡déjeme saber dónde comprarlas porque yo también quiero una!

    – Lundin

    6 de marzo de 2013 a las 14:58

  • INT8_MAX es 127. Es cierto que d2<<8 puede demostrarse que no se desborda cuando d2<=127pero la razón es que INT_MAX se requiere que sea al menos 32767 pero no se requiere que sea más grande.

    – R.. GitHub DEJA DE AYUDAR A ICE

    6 de marzo de 2013 a las 15:17

  • La desventaja del modelo de stackoverflow es que la mayor parte de esta discusión ahora se vuelve basura debido a una edición de la publicación original. Proporcionando INT_MAX == 32767, INT8_MAX es el valor máximo por coincidencia. Cuando INT_MAX >= 32768, INT8_MAX no tiene sentido.

    – autista

    6 de marzo de 2013 a las 15:18


  • @Lundin El peligro no es necesariamente cambiando a los bits de signo; Usar un valor que no se puede representar como un inten una expresión que tiene int escribe parece una descripción más apropiada para este comportamiento indefinido.

    – autista

    06/03/2013 a las 15:31


(uint16_t)((d2 << 8) + (d1 & 0x00ff))

¿Ha sido útil esta solución?