variable tipos tipo que programacion long float ejemplos ejemplo datos dato c casting int unsigned htonl

c - que - tipos de variables en java netbeans



¿La conversión entre int firmado y sin firmar mantiene el patrón de bits exacto de la variable en la memoria? (3)

Quiero pasar un entero x 32 bits con signo a través de un socket. Para que el receptor sepa qué orden de bytes esperar, estoy llamando a htonl(x) antes de enviar. htonl embargo, htonl espera un uint32_t y quiero estar seguro de lo que sucede cuando int32_t mi int32_t a un uint32_t .

int32_t x = something; uint32_t u = (uint32_t) x;

¿Es siempre el caso que los bytes en x y u sean exactamente iguales? ¿Qué hay de echar atrás?

uint32_t u = something; int32_t x = (int32_t) u;

Me doy cuenta de que los valores negativos se convierten en grandes valores sin signo, pero eso no importa, ya que simplemente estoy devolviendo al otro extremo. Sin embargo, si la conversión se confunde con los bytes reales, no estoy seguro de que la devolución devuelva el mismo valor.


En general, la conversión en C se especifica en términos de valores, no de patrones de bits: los primeros se conservarán (si es posible), pero los últimos no necesariamente así. En el caso de las representaciones de complemento de dos sin relleno, lo cual es obligatorio para los tipos de enteros fijos con, esta distinción no importa y el elenco de hecho será un noop.

Pero incluso si la conversión de firmado a no firmado hubiera cambiado el patrón de bits, volver a convertirlo habría restablecido el valor original, con la advertencia de que la conversión fuera de rango sin signo a firmada está definida por la implementación y puede generar una señal. rebosar.

Para una portabilidad completa (que probablemente será una exageración), deberá usar el tipo de letra en lugar de la conversión. Esto se puede hacer de una de dos maneras:

A través de moldes de puntero, es decir

uint32_t u = *(uint32_t*)&x;

con lo que debe tener cuidado ya que puede violar reglas de escritura efectivas (pero está bien para variantes con signo / sin signo de tipos enteros) o mediante uniones, es decir,

uint32_t u = ((union { int32_t i; uint32_t u; }){ .i = x }).u;

que también se puede usar para, por ejemplo, convertir de double a uint64_t , lo que no puede hacer con los lanzamientos de punteros si desea evitar un comportamiento indefinido.


Esto siempre debe ser seguro, porque se garantiza que los tipos intXX_t están en el complemento de dos si existen:

7.20.1.1 Tipos de enteros de ancho exacto El nombre de typedef intN_t designa un tipo de entero con signo con ancho N, sin bits de relleno y una representación de complemento de dos. Por lo tanto, int8_t denota un tipo entero con signo con un ancho de exactamente 8 bits.

Teóricamente, la conversión uint32_t de uint32_t a int32_t está definida por la implementación, como para todas las conversiones unsigned a signed . Pero no puedo imaginar mucho que una plataforma haría de manera diferente a lo que usted espera.

Si desea estar realmente seguro de esto, aún puede realizar esa conversión manualmente. Solo > INT32_MAX probar un valor para > INT32_MAX y luego hacer un poco de matemáticas. Incluso si lo haces sistemáticamente, un compilador decente debería poder detectar eso y optimizarlo.


Los moldes se utilizan en C para significar tanto "conversión de tipo" como "desambiguación de tipo". Si tienes algo como

(float) 3

Entonces es una conversión de tipo, y los bits reales cambian. Si usted dice

(float) 3.0

Es una desambiguación tipo.

Suponiendo una representación de complemento a 2 (vea los comentarios a continuación), cuando convierte un int en un unsigned int , el patrón de bits no cambia, solo su significado semántico; Si lo devuelves, el resultado siempre será correcto. Cae en el caso de desambiguación de tipo porque no se cambian los bits, solo la forma en que la computadora los interpreta.

Tenga en cuenta que, en teoría, el complemento de 2 no se puede usar, y unsigned y signed pueden tener representaciones muy diferentes, y el patrón de bits real puede cambiar en ese caso.

Sin embargo, desde C11 (el estándar C actual), se le garantiza que sizeof(int) == sizeof(unsigned int) :

(§6.2.5 / 6) Para cada uno de los tipos de enteros con signo, hay un tipo de entero sin signo correspondiente (pero diferente) (designado con la palabra clave sin firmar) que usa la misma cantidad de almacenamiento (incluida la información de signos) y tiene la misma requisitos de alineación [...]

Yo diría que en la práctica, puedes asumir que es seguro.