c - restas - ¿Qué tipo para restar 2 size_t''s?
resta ejemplos (4)
¿Qué tipo de C debería usarse para representar la diferencia entre los tamaños de dos objetos?
Como size_t
no está firmado, algo como
size_t diff = sizeof (small_struct) - sizeof (big_struct);
obviamente no sería correcto y me parece que no hay un equivalente real firmado.
ptrdiff_t
suena un poco tentador, pero
- como su nombre lo dice es para restar punteros.
- He leído que, por ejemplo, las plataformas segmentadas como DOS tienen un tamaño de objeto máximo de 64k, que se puede representar en 16 bits. Sin embargo, los punteros lejanos están compuestos por un valor de segmento de 16 bits y un valor de desplazamiento de 16 bits. ¿No haría eso
ptrdiff_t
en una plataforma de 32 bits también? Si es así, la diferencia entre dos objetos de tamaño solo requiere 16 bits, pero el uso de ptrdiff_t le dará una variable de 32 bits de ancho, por lo que es subóptima.
Entonces, ¿cuál es el tipo adecuado y portátil para trabajar con ese valor?
Edit:
sé sobre ssize_t, pero es
- no es parte de la norma C.
- en realidad no está destinado para tal uso, sino para devolver un valor de error de tamaño o negativo.
Cuando estoy realmente preocupado por problemas de desbordamiento como ese (especialmente cuando se trabaja en aritmética modular donde los valores "negativos" se ubican en un lugar distinto a ~0
), simplemente lo dividí en dos casos:
if (a > b) {
size_t diff = a - b;
} else {
size_t diff = b - a;
// code here subtracts diff rather than adds it, etc.
}
No hay ningún tipo de entero C con signo que pueda contener todos los valores de un valor size_t
.
No hay un tipo de datos estándar que garantice que sea 100% seguro para lo que estás tratando de hacer. Para la evidencia, imagine que size_t
es realmente uint64_t
, lo cual es completamente posible. Entonces, no hay ningún tipo de datos C estándar que se garantice que tenga un rango positivo que coincida con uint64_t
y que también maneje valores negativos.
Por lo tanto, la respuesta contundente a su pregunta es "sin tipo de datos" (suponiendo que se cumpla estrictamente el estándar C, que parece que desea).
Sin embargo, no está claro en su caso de uso, y es posible que pueda aprovechar la aritmética modular para manejar valores "negativos". Por ejemplo, el siguiente código hace que d2
sea 4
debido a la aritmética modular, lo que permite que el código actúe como si se firmara size_t
:
#include <stdio.h>
#include <stdint.h>
int main()
{
size_t d1 = sizeof(int32_t) - sizeof(int64_t);
size_t d2 = sizeof(int64_t) + d1; // Add difference (even if d1 is "negative"*)
printf("d1: %zu/n", d1);
printf("d2: %zu/n", d2);
return 0;
// * By "negative" I mean that d1 would be negative if size_t were signed
}
La aritmética modular puede no ser suficiente para usted en su caso, pero para otros puede serlo.
Podrías hacer esto:
size_t diff = std::abs(static_cast <int> (sizeof (small_struct) - sizeof (big_struct)));