Valor inesperado después del casting tipo en c
Estaba implementando el código para enviar datos a través de una toma en bruto. Como parte de eso, tengo que construir un paquete IP. Pero estoy enfrentando el problema como se explica a continuación utilizando un programa de muestra.
#include
struct iph {
unsigned char ihl:4;
unsigned char ver:4;
unsigned char data;
unsigned char data1;
};
int main()
{
char buff[3] = {0};
struct iph *ptr = (struct iph *)buff;
ptr->ihl = 5;
ptr->ver = 4;
ptr->data = 0xAB;
ptr->data1 = 0xCD;
printf("%x %x %x\n", buff[0], buff[1], buff[2]);
}
Aquí la salida que estoy esperando 45 ab cd
Pero me estoy poniendo 45 ffffffab ffffffcd
. ¿Puede alguien explicar cómo está sucediendo esto y compartir una solución para obtener el valor esperado?
Pregunta hecha hace 3 años, 5 meses, 6 días - Por compilercaptain
4 Respuestas:
-
char
está firmado en su máquina y0xab
es un valor negativo para los tipos de datos firmados de 8 bits. Así que cuando se promueve, se promueve al mismo valor negativo y eso es0xffffffab
como unint
.Solución: uso
unsigned char
Respondida el Dec 17, 2020 a las 10:05 - por stackscripter
Votos positivos: 0 | Votos negativos: 0 -
Usted código tiene dos problemas, primero
buff
array tiene que ser 4 tamaño no 3, segundo su tipo de buff tiene que serunsigned char
.Respondida el Dec 17, 2020 a las 10:14 - por codechampionx
Votos positivos: 0 | Votos negativos: 0 -
El problema que estás experimentando se debe al uso de campos de bits en la estructura
iph
. Los campos de bits en C pueden ser propensos a comportamientos no deseados y dependen de la implementación del compilador.Cuando asignas los valores 0xAB y 0xCD a
ptr->data
yptr->data1
respectivamente, estos están siendo tratados como valores de tipochar
(signed char por defecto). Comounsigned char
es de 1 byte en tamaño, el rango de valores posibles va desde 0 a 255. En el caso de0xAB
y0xCD
, que son mayores a 127, estos se interpretan como números negativos cuando son asignados achar
ounsigned char
.Para corregir esto, puedes cambiar los campos
data
ydata1
aunsigned char
y asegurarte de que los valores asignados en ellos estén dentro del rango de 0 a 255.Aquí tienes el código modificado:
c
include struct iph { unsigned char ihl:4; unsigned char ver:4; unsigned char data; unsigned char data1; }; int main() { unsigned char buff[3] = {0}; struct iph ptr = (struct iph )buff; ptr->ihl = 5; ptr->ver = 4; ptr->data = 0xAB; ptr->data1 = 0xCD; printf("%x %x %x\n", buff[0], buff[1], buff[2]); return 0; }Ahora, al declarar
buff
comounsigned char
, el programa mostrará la salida esperada45 ab cd
.Respondida el Dec 18, 2020 a las 10:09 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
El problema en el código es que estás asumiendo que los miembros de la estructura
iph
se almacenan en bytes contiguos en el búferbuff
. Sin embargo, en la mayoría de las arquitecturas, los miembros de la estructura se almacenan según su alineación de datos, y los miembros más grandes (comodata
ydata1
) pueden ocupar varios bytes.En tu caso, los miembros
ihl
yver
son de 1 byte cada uno y se almacenan en el orden en que se declaran en la estructura. Sin embargo, los miembrosdata
ydata1
son de 1 byte cada uno y, según la alineación de datos de la arquitectura, pueden almacenarse en bytes diferentes.Para solucionar este problema, puedes utilizar la función
memcpy()
para copiar los datos de la estructura al búfer, asegurándote de alinearlos correctamente. Aquí tienes un código modificado:c
include include struct iph { unsigned char ihl:4; unsigned char ver:4; unsigned char data; unsigned char data1; }; int main() { char buff[3] = {0}; struct iph iph; iph.ihl = 5; iph.ver = 4; iph.data = 0xAB; iph.data1 = 0xCD; memcpy(buff, &iph, sizeof(iph)); printf("%x %x %x\n", buff[0], buff[1], buff[2]); return 0; }Esta versión del código utiliza
memcpy()
para copiar toda la estructuraiph
al búferbuff
, asegurándose de que los miembros se alineen correctamente. La salida del código ahora debería ser45 ab cd
, como se esperaba.Respondida el Dec 18, 2020 a las 10:16 - por Gemini
Votos positivos: 0 | Votos negativos: 0