Go Down

Topic: Solucionado-Conversiones automáticas de tipo, comparaciones de números con signo (Read 989 times) previous topic - next topic

fernando david

Hola, estudiando las conversiones de tipos automáticas me topo con algo que lo logro comprender.
El código lo hice para poder entender el tema de las conversiones automáticas cuando hacemos comparaciones entre números con signo y sin signo.

Code: [Select]


unsigned int dato=40;
int i=-1;
void setup() {
 Serial.begin(9600);
 Serial.println(i); //me lo mestra con signo en decimal
 Serial.println((unsigned int)i);//me lo mestra sin signo en decimal
 Serial.println((unsigned int)i,BIN);//me lo mestra sin signo en binario
 Serial.println(i,BIN);//me lo mestra con signo en binario
 
 if (dato>-1){
   Serial.print("deberia ejecutarse siempre este bucle");
 }
 else {
   Serial.print("esto no deberia imprimirse nunca!");
 }
}
void loop() {
}


1)   Entiendo que si no le decimos nada al compilador, este toma los literales como enteros con signo. Es correcto esto?
2)   En el código que expongo no logro entender por qué en el quinto Serialprintln, me musestra tantos bits? El compilador no hiso una conversión a int sin signo (16bit)? pense que era lo que deberia hacer, o lo llevo a otro tipo de dato.

al que me pueda aclarar el panorama se lo agradeceré.

nayma

Puedes ponernos lo que te sale por pantalla. Por que en el loop no hay nada, por lo tanto el código solo se ejecutará una vez y después se queda dando vueltas en el loop haciendo.... nada.

fernando david

bien lo que me muestra es:


Lo que decía, el primer print me muestra el i en formato decimal con su valor asignado en int i=-1;  y me muestra lo esperado,"-1"

En el segundo print se le saca el signo a i y lo muestro en decimal, también me muestra lo esperado, 65535. Esto es porque al sacarle el signo, el dato queda en complemento a dos, lo único que cambia es como el compilador ve ese dato, antes lo veía como un numero con su signo, ahora lo ve solo como un numero, por lo que toma sus 16 bits, que están a 1, 65536=0xFFFF=1111111111111111 .

En el tercer print me muestra el i otra vez sin signo pero en este caso en binario, 1111111111111111.

La confusión me la da el último print, que me debería mostrar -1 en binario, que para mi seria 1111111111111111 pero que me muestra 11111111111111111111111111111111.

Lo que creía hasta ahora era que 0xFFFF= 1111111111111111=65536  esto tomando al número sin signo, ahora si lo tomamos con signo, sigue siendo 1111111111111111 pero ahora el compilador lo interpreta como tal, 15 bit mas uno de sigo por lo que seria =-1 expresado en complemento a dos.     

El código no tiene nada en loop porque como decía, es solo para estudiar este tema, no tiene ninguna utilidad práctica.
Gracias .


PascuaL

Hola.
Según tu código eso sí debería imprimirse, porque le dices que :
Code: [Select]
if (dato>-1){ // Tu dato no es mayor que -1, es -1...por lo tanto..
    Serial.print("deberia ejecutarse siempre este bucle");
  }
  else {
    Serial.print("esto no deberia imprimirse nunca!");// al no ser tu condición, salta al else.
  }


Un saludo.

Luis_AM3C

Hola,

       Supongo que la funcion print esta hecha con un int de 32 bits.

      Cuando comparas dato>-1 estas comparando dos tipos de datos diferentes, asi que tiene que convertir uno para compararlo, por el resultado se esta convirtiendo el -1 a unsigned y se obtiene 65534 y por eso la condición es falsa.

Saludos.

fernando david

Hola, gracias por sus respuestas.
PascuaL, si relees mi primer mensaje en el post, tu respuesta no corresponde a mis preguntas.  Yo tengo muy en claro el por que  dato nunca es mayor que -1 y por lo tanto porque nunca va a entrar al if.

Luis_AM3C,  creo que lo que dices del que el print espera un tipo de datos... puede tener algo que ver, pero sigo sin entender.

Muchas gracias a ambos por responder.

Vuelvo a pegar mis preguntas para que quede bien claro que es lo que no entiendo y además rectificar la segunda, que donde decía quinto debería decir cuarto.
1)   Entiendo que si no le decimos nada al compilador, este toma los literales como enteros con signo. Es correcto esto?
2)   En el código que expongo no logro entender por qué en el cuarto Serialprintln, me muestra tantos bits? El compilador no hiso una conversión a int sin signo (16bit)? pensé que era lo que debería hacer, o lo llevo a otro tipo de dato.

Igor R

Hola,

Quote
Serial.println((unsigned int)i,BIN);


Echando un vistazo rápido en \hardware\arduino\cores\arduino\Print.cpp
Si no me equivoco Serial hereda de Stream, que a su vez de print (lo he mirado en Arduino versión 22). Seguramente cambie en versiones posteriores, pero sirve de idea de por donde tienes que investigar para resolver tus dudas.... ;)

void Print::print(unsigned int n, int base)
{
 print((unsigned long) n, base);
}

Internamente se hace un cast a unsigned long (que es una variable de 4 bytes=32 bits) .


Saludos,



Igor R.


fernando david

Hola Igor R, es lo que necesitaba saber! Gracias.

Agradezco a todos lo que se toman el tiempo en responder, Arduino no es solo la placa, sino la enorme comunidad!

Go Up