Cada vez que escribe una ecuación en C / C ++, los tipos de datos que se utilizan tienen un efecto muy real en la salida de la ecuación.
Cada tipo como int
, float
y unsigned long
tener diferentes comportamientos, y tomar una cierta cantidad de espacio en la memoria para almacenar.
int
(en arduino) se almacena en 16 bits, con la mitad de sus valores dados a números negativos, la mitad 1 dada a valores positivos y un valor dado a 0. Eso le da un rango de -2 ^ 15 (-32,768) a + 2 ^ 15-1 (32,767).
unsigned long
(en arduino) es de 32 bits, pero ninguno se designa como negativo. su rango es entonces de 0 a 2 ^ 32-1 (4294967295).
¿Qué tipo de matemática? ¿Qué otro tipo de procesamiento se excluye al trabajar con millis?
El quid de la cuestión es que cuando el tiempo de devolución de Millis ha pasado de 32767 y trataste de almacenarlo en un int, el arduino no pudo hacerlo, porque int
no puede contener un número tan grande. El tipo de matemática que está fuera de los límites es la matemática que sucede a tipos de datos más pequeños, no a operaciones específicas. Quizás estos ejemplos ayuden:
int i = 32767;
Serial.println(i);
//No problems here; it fits just fine
32767
i = 32767 + 1;
Serial.println(i);
//Oh no, the value didn't fit
-32768
unsigned long fake_millis = 42000;
i = fake_millis;
Serial.println(i);
//This is an example of millis going past an int
-23536
i = -10;
unsigned int j = i;
Serial.println(j);
//no way to put a negative number in an unsigned value
65526
uint32_t k = fake_millis;
Serial.println(k);
//unsigned long is a uint32_t on arduino; this works great!
42000
La forma en que esto se implementa es realmente genial; Si está interesado en saber de dónde provienen estos números y por qué se extienden de la manera en que lo hacen, debe buscar las mismas explicaciones de las representaciones de números complementarios de dos.
unsigned long
puede cambiar con diferentes plataformas (por ejemplo, x86),uint32_t
siempre habrá 32 bits sin signo en todas partes.32767 + 1
) produce un comportamiento indefinido, que casi siempre es algo malo . Sus otros ejemplos son comportamientos documentados en los que puede confiar.millis()
devuelve ununsigned long
, que es un entero sin signo de 32 bits en el Arduino. Cuando intentas hacer algo comounsigned int time = millis() - 1000
, intentas almacenarlo en un entero sin signo de 16 bitsunsigned int
. Un entero de 16 bits nunca puede contener un valor de 32 bits.De acuerdo con la especificación C , párrafo 6.3.1.3, los 16 bits superiores se descartan.
Si es posible, mantenga la
millis()
salida enunsigned long
y solo use tipos de datos con menos bits cuando esté absolutamente seguro de que no perderá bits.Aquí hay más información sobre moldes explícitos en C: https://stackoverflow.com/a/13652624/1544337
fuente
uint32_t
que resulta ser ununsigned long
on arduino?unsigned long
.int time = millis() - 1000
), el resultado es similar: los 16 bits superiores se descartan. Esta vez, el estándar C dice que el resultado está definido por la implementación, y el comportamiento se especifica en la documentación de gcc sobre el comportamiento de los enteros definido por la implementación (cuarto punto).Cuando quieras hacer cosas con millis () solo recuerda inicializar tu variable con el tipo "uint32_t"
Entonces, haga algo como "uint32_t last_millis" donde almacenará la salida de la función "millis ()".
De lo contrario, como dijeron los demás, se desbordaría al pasar de 31,000, lo que sucederá bastante rápido.
fuente